我有一个SensorSample POJO列表

public class SensorSample {

    private Device.SensorType sensorType; // This is an enum
    private double sample;
    private long timestamp;

    // Constructor

    // Setters

    // Getters

}

我需要按timestamp将它们分组,以便同一天的所有SensorSample在一起。然后,我需要减少它们,以便每天只有一个SensorSample,并且它的sample的值是当天所有对象的sample值的平均值。有没有办法用Streams做到这一点?

到目前为止,我已经将它们组合在一起:
Map<Long, List<SensorSample>> yearSamples = samples.stream()
                .collect(groupingBy(sample -> SECONDS_IN_A_DAY*Math.floorDiv(sample.getTimestamp(), SECONDS_IN_A_DAY)));

但是我不知道该怎么做。

最佳答案

好像您想要一个List<SensorSample>,结果是groupingBy之后的每个组都被简化为一个SensorSample

List<SensorSample> result = samples.stream()
                .collect(groupingBy(sample -> SECONDS_IN_A_DAY*Math.floorDiv(sample.getTimestamp(), SECONDS_IN_A_DAY))
                .entrySet()
                .stream()
                .map(e -> {
                    SensorSample sensorSample = new SensorSample();
                    sensorSample.setTimestamp(e.getKey());
                    double average = e.getValue().stream()
                            .mapToDouble(SensorSample::getSample)
                            .average().orElse(0);
                    sensorSample.setSample(average);
                    sensorSample.setSensorType(e.getValue().get(0).getSensorType());
                    return sensorSample;
                }).collect(Collectors.toList());
map逻辑似乎有点大,所以我考虑将其重构为这样的方法:
private static SensorSample apply(Map.Entry<Long, List<SensorSample>> e) {
        SensorSample sensorSample = new SensorSample();
        sensorSample.setTimestamp(e.getKey());
        double average = e.getValue().stream()
                .mapToDouble(SensorSample::getSample)
                .average().orElse(0);
        sensorSample.setSample(average);
        sensorSample.setSensorType(e.getValue().get(0).getSensorType());
        return sensorSample;
}

然后,流管道将变为:
List<SensorSample> result = samples.stream()
                .collect(groupingBy(sample -> SECONDS_IN_A_DAY*Math.floorDiv(sample.getTimestamp(), SECONDS_IN_A_DAY))
                .entrySet()
                .stream()
                .map(Main::apply)
                .collect(Collectors.toList());

其中Main是包含apply方法的类。

09-27 00:08