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

3

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

这些样本是过去一个月的每小时测量值。我想计算每天的总体平均值。我可以在数据流中计算出现次数,也可以计算每天所有平均值的总和,但我不知道如何将这两个内容合并到一个数据流中。
以下是我的进展:
将每天所有平均值相加(我按日期属性的子字符串进行分组以按天分组,例如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();
            })));

获取每天的样本数: Map counts =

Arrays.stream(samples).collect(Collectors.groupingBy((PricingSample e) -> {
            return e.getTime().toString().substring(0, 10);
        },
                Collectors.counting()
            ));
1个回答

2
如果你想要平均值,可以使用averagingDouble。这样就不需要计算总和和样本数了。
Map<String, Double> averages = 
    Arrays.stream(samples)
          .collect(Collectors.groupingBy(e -> e.getTime().toString().substring(0, 10),
                                         Collectors.averagingDouble(PricingSample::getAverage)));

如果您希望按照键(即日期)对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)));

太好了,谢谢。但是现在我想起来了,有没有办法按日期对输出的Map进行排序?它是一个字符串值,所以我不太确定这是否可行。 - Matt
@Matt 如果你想要字符串按字典顺序排序,只需将TreeMap::new作为传递给groupingBy的第二个参数添加即可。这将导致输出的Map成为一个TreeMap,其中键已排序。 - Eran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接