[英]Using Java Streams to group together a List of objects by an attribute and reduce them to a new list of object with the average of another attribute
我有一个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)));
但我不知道如何进一步。
我认为,这样的事情。 要查找组的平均数:
Map<Long, Double> averages = samples.stream()
.collect(groupingBy(SensorSample::getTimestamp,
averagingDouble(SensorSample::getSample)));
我没有扩展你当天的公式,我认为如果我只是调用getTimestamp
并保留详细信息,它更具可读性。 如果向SensorSample
添加了getDay
方法,那么您的代码可能更具可读性。
如果你提供了一个MCVE,这也会更容易测试,因为测试上面的代码只需要一个部分类就可以了。
看起来好像你想要一个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
方法的类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.