繁体   English   中英

LinkedHashMap 中的平均值,以日期为 keySet,按星期几

[英]Average values in LinkedHashMap with dates as keySet by day of week

我有一个LinkedHashMap<Date, Double> ,其中键是日期和与每个条目关联的 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。

使用流

您可以使用 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);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM