LinkedHashMap中的平均值,按星期几作为日期的键集

问题描述 投票:0回答:1

我有一个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 date iterator java-6
1个回答
0
投票

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

EDIT:没有流:

    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);
    }
© www.soinside.com 2019 - 2024. All rights reserved.