[英]java streams: straightforward reduce
我有一個MetricGroup
流,其中:
public class MetricGroup {
private int uploadedDocs;
private long uploadedKbs;
// getters and setters
}
我需要在一個指標中對所有指標進行sumarize。 我的意思是,我需要將所有metric.uploadedDocs
添加到sumMetric.uploadedDocs
和metric.uploadedKds
到sumMetric.uploadedKbs
。
我發現我需要某種reduce
Stream.of(new MetricGroup(1,100), new MetricGroup(1,200))
.reduce(????);
有任何想法嗎?
你可以使用reduce
這個重載:
T reduce(T identity,
BinaryOperator<T> accumulator)
像這樣:
.reduce(new MetricGroup(0, 0),
(x, y) -> new MetricGroup(
x.getUploadedDocs() + y.getUploadedDocs()
x.getUploadedKbs() + y.getUploadedKbs()
)
)
您還可以使用collect
方法:
private static MetricGroup combine(MetricGroup x, MetricGroup y) {
x.setUploadedDocs(x.getUploadedDocs() + y.getUploadedDocs());
x.setUploadedKbs(x.getUploadedKbs() + y.getUploadedKbs());
return x;
}
// ....
.collect(() -> new MetricGroup(0, 0),
YourClass::combine,
YourClass::combine
)
為了避免在reduce
調用期間創建多個/多個MetricGroup
對象,可以分別進行兩次調用以對UploadedDocs
和UploadedKbs
求和,然后構造一個表示結果的新MetricGroup
。
int uploadedDocsSum = source.stream().mapToInt(MetricGroup::getUploadedDocs).sum();
long uploadedKbsSum = source.stream().mapToLong(MetricGroup::getUploadedKbs).sum();
MetricGroup result = new MetricGroup(uploadedDocsSum, uploadedKbsSum);
可以說更具可讀性......
只需傳入一個lambda(將操縱現有的MetricGroup)
Stream.of(new MetricGroup(1, 100), new MetricGroup(1, 200))
.reduce((a, b) -> {
a.setUploadedDocs(a.getUploadedDocs() + b.getUploadedDocs());
a.setUploadedKbs(a.getUploadedKbs() + b.getUploadedKbs());
return a;
});
// Optional[F.MetricGroup(uploadedDocs=2, uploadedKbs=300)]
或者,真正獲得一個新的MetricGroup(不需要操作現有的MetricGroup)
Stream.of(new MetricGroup(1, 100), new MetricGroup(1, 200))
.reduce((a, b) -> new MetricGroup(a.getUploadedDocs() + b.getUploadedDocs(), a.getUploadedKbs() + b.getUploadedKbs()));
與java流一樣,您實際上不必使用它們。 我建議創建一個簡單的簡化輔助方法:
public static MetricGroup reduce(Iterable<? extends MetricGroup> metrics){
int uploadedDocs = 0;
long uploadedKbs = 0L;
for(MetricGroup metric : metrics){
uploadedDocs += metric.getUploadedDocs();
uploadedKbs += metric.getUploadedKbs();
}
return new MetricGroup(uploadedDocs, uploadedKbs);
}
如果你不能改變你開始使用流,你仍然可以使用上面的方法,只需傳遞一個對Stream.iterator()
方法的引用:
MetricGroup reduced = reduce(stream::iterator);
如果你想使用簡化,我建議將MetricGroup
設為值類型,方法是將字段MetricGroup
final,添加零,並用組合方法替換setter。
public class MetricGroup {
private final int uploadedDocs;
private final long uploadedKbs;
// obvious constructor
// getters
public static final ZERO = new MetricGroup(0, 0);
public MetricGroup add(MetricGroup a, MetricGroup b) {
return new MetricGroup(a.uploadedDocs + b.upLoadedDocs,
a.uploadedKbs + b.uploadedKbs);
}
public MetricGroup uploadOneDoc(long kbs) {
return new MetricGroup(uploadedDocs + 1, uploadedKbs + kbs);
}
}
這樣可以很好地執行流操作:
MetricGroup sum = metricGroups.stream()
.reduce(MetricGroup.ZERO, MetricGroup::add);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.