我有一个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
方法的类。