I have an array of PricingSamples objects :
public class PricingSample {
private Date time;
private Double average;
public PricingSample(Date time, Double average) {
this.time = time;
this.average = average;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public Double getAverage() {
return average;
}
public void setAverage(Double average) {
this.average = average;
}
}
The samples are hourly for the past month. I would like to calculate the overall average for each day. I am able to count the number of occurencies in a stream and I am also able to count the sum of all the averages for each day, I just don't know how to combine those to things into one stream.
Here is what I got to.
Summing all averages for each day (I group by the substring of the Date property so it groups by day i.e. Thu Apr 26):
Map<String, Double> counts = Arrays.stream(samples).collect(Collectors.groupingBy((PricingSample e) -> {
return e.getTime().toString().substring(0, 10);
},
Collectors.summingDouble((PricingSample e) -> {
return e.getAverage();
})));
Getting the number of samples for each day: Map counts =
Arrays.stream(samples).collect(Collectors.groupingBy((PricingSample e) -> {
return e.getTime().toString().substring(0, 10);
},
Collectors.counting()
));
If you want the average, use averagingDouble. This way you don't need to calculate the sum and the number of samples.
Map<String, Double> averages =
Arrays.stream(samples)
.collect(Collectors.groupingBy(e -> e.getTime().toString().substring(0, 10),
Collectors.averagingDouble(PricingSample::getAverage)));
If you wish to sort the Map by its keys (the days), you can force the output to be a TreeMap:
Map<String, Double> averages =
Arrays.stream(samples)
.collect(Collectors.groupingBy(e -> e.getTime().toString().substring(0, 10),
TreeMap::new,
Collectors.averagingDouble(PricingSample::getAverage)));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With