1

我有一个LinkedHashMap<Date, Double>where 键是日期和一个与每个条目关联的 Double 值。每小时有一个条目。

我需要平均一周中的每一天的值,所以我得到一个列表,其中包含第一个月的所有星期一条目、第一个月的所有星期二条目、第一个月的所有星期三条目等的平均值。然后在接下来的几个月里做同样的事情。输出将是这样的:

KEY(Day of week per month)   |   VALUE(Avg of all values for the day of week on the month)
------------------------------------------------------------------------------------------
Month1Sunday                 |   23423
Month1Monday                 |   6452
Month1Tuesday                |   94402

...

Month2Sunday                 |   342755
Month2Monday                 |   10923

这是我到目前为止所得到的:

private void getDailyBase(Map<Date, Double> hourlyPrices){
    Calendar cal = Calendar.getInstance();
    int month = 0;
    boolean firstIteration = true;
    int counter = 0;
    Double acumValue =0D;
    Double result;
    Map<Integer, Double> averageAccumulator = new LinkedHashMap<Integer, Double>();

    for (Map.Entry<Date, Double> entry : hourlyPrices.entrySet()){
        cal.setTime(entry.getKey());
        if (firstIteration){
            month = cal.get(Calendar.MONTH);
            firstIteration = false;
        }

        if (cal.get(Calendar.MONTH) == month){
            acumValue += entry.getValue();
            counter++;
        }else {
            result = acumValue/counter;
            month = cal.get(Calendar.MONTH);
            averageAccumulator.put(month, result);
            counter = 0;
            acumValue = 0D;
        }
    }
}

我可以累积每个月的值并将它们平均。但是当我试图找出或构建以星期为基础的结构时,我只是不知道如何去做或从哪里开始。我尝试过不同的迭代结构,但我想我没有看到全貌。

我正在使用 Java 6。

4

1 回答 1

1

使用流

您可以使用 Java 8 流非常快地做到这一点,但是这种特定的用法可能会变得有点复杂,因为您可能希望将其拆分一下。

    Calendar instance = Calendar.getInstance();
    Map<String, Double> weekInAYearToAverage =
            hourlyPrices
                    .entrySet()
                    .stream()
                    // Group all entries, where key is "MonthXDayName" and value is a list of entries
                    // This will give us Map<String, List<Entry<Date, Double>>>
                    .collect(Collectors.groupingBy(dateDoubleEntry -> {
                        instance.setTime(dateDoubleEntry.getKey());
                        // Create String key as "MonthXDayName"
                        return "Month" + instance.get(Calendar.MONTH) +
                                DayOfWeek.of(instance.get(Calendar.DAY_OF_WEEK))
                                        .getDisplayName(TextStyle.FULL, Locale.ENGLISH);
                    }))
                    // This would be a good place to split this line
                    .entrySet()
                    .stream()
                    // Map all groups, so we will have map where key is "MonthXDayName" and value is an average value or 0, if no values
                    .collect(Collectors.toMap(Map.Entry::getKey,
                            e -> e.getValue()
                                    .stream()
                                    .mapToDouble(Map.Entry::getValue)
                                    .average()
                                    .orElse(0)));

没有流

对于 Java 6 和 7,在将流引入 Java 之前,使用常规循环。

    Calendar instance = Calendar.getInstance();
    // Group entries by "MonthXDayName"
    Map<String, List<Map.Entry<Date, Double>>> groupedEntries = new HashMap<String, List<Map.Entry<Date, Double>>>();
    for (Map.Entry<Date, Double> entry : hourlyPrices.entrySet()) {
        instance.setTime(entry.getKey());
        String key = "Month" + instance.get(Calendar.MONTH) +
                DayOfWeek.of(instance.get(Calendar.DAY_OF_WEEK))
                        .getDisplayName(TextStyle.FULL, Locale.ENGLISH);
        if (!groupedEntries.containsKey(key)) {
            // If there will be a lot of entries, you might consider using LinkedList, as it's faster when adding big number of entries
            groupedEntries.put(key, new ArrayList<Map.Entry<Date, Double>>());
        }
        groupedEntries.get(key).add(entry);
    }
    // Calculate average for every group
    Map<String, Double> weekInAYearToAverage = new HashMap<String, Double>();
    for (Map.Entry<String, List<Map.Entry<Date, Double>>> entry : groupedEntries.entrySet()) {
        String key = entry.getKey();
        double avg = 0;
        if (entry.getValue().size() > 0) {
            for (Map.Entry<Date, Double> hourlyEntry : entry.getValue()) {
                avg += hourlyEntry.getValue();
            }
            avg /= entry.getValue().size();
        }
        weekInAYearToAverage.put(key, avg);
    }
于 2019-11-28T12:53:59.480 回答