我有一个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)));
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);
}