[英]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.