简体   繁体   English

使用Java中的流对对象数组进行分组并计算平均值

[英]Group and calculate average of object array using stream in Java

I have an array of PricingSamples objects : 我有一个PricingSamples对象数组:

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 ie Thu Apr 26): 汇总每天的所有平均值(我按Date属性的子字符串分组,因此按日期分组,即4月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 . 如果需要平均值,请使用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的键(日期)对Map进行排序,则可以将输出强制为TreeMap

Map<String, Double> averages = 
    Arrays.stream(samples)
          .collect(Collectors.groupingBy(e -> e.getTime().toString().substring(0, 10),
                                         TreeMap::new,
                                         Collectors.averagingDouble(PricingSample::getAverage)));

Try this out, 试试看

final Map<Date, Double> averageByDate = pricingSamples.stream().collect(
        Collectors.groupingBy(PricingSample::getTime, Collectors.averagingDouble(PricingSample::getAverage)));

In case if you are using an array, change it like so, 如果您使用的是数组,请像这样更改它,

final Map<Date, Double> averageByDate = Stream.of(pricingSamples).collect(
                Collectors.groupingBy(PricingSample::getTime, Collectors.averagingDouble(PricingSample::getAverage)));

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

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