我有MetricGroup
的信息流,其中:
public class MetricGroup {
private String application;
private int uploadedDocs;
private long uploadedKbs;
// getters and setters
}
我需要总结所有应用程序指标。我的意思是,对于每个应用程序(MetricGroup.application
,我需要将所有metric.uploadedDocs
添加到sumMetric.uploadedDocs
中,并将metric.uploadedKds
添加到sumMetric.uploadedKbs
中。
我发现我需要某种groupingBy
Stream.of(
new MetricGroup("app1", 1,100),
new MetricGroup("app1", 1,300),
new MetricGroup("app2", 1,200)
)
.collect(Collector.groupingBy(MetricGroup::getApplication, accumulator??, combiner??)
结果将是具有以下内容的流:
< MetricGroup("app1", 2, 400) , MetricGroup("app2", 1, 200) >
有什么想法吗?
答案 0 :(得分:4)
您可以按application
分组,然后将结果映射到MetricGroup
:
source.stream()
.collect(groupingBy(MetricGroup::getApplication))
.entrySet().stream()
.map(s -> new MetricGroup(s.getKey(),
s.getValue().stream().mapToInt(MetricGroup::getUploadedDocs).sum(),
s.getValue().stream().mapToLong(MetricGroup::getUploadedKbs).sum()))
.collect(Collectors.toList());
答案 1 :(得分:2)
如果可以将以下复制构造函数和merge
方法添加到MetricGroup
类中:
public MetricGroup(MetricGroup another) {
this.application = another.application;
this.uploadedDocs = another.uploadedDocs;
this.uploadedKbs = another.uploadedKbs;
}
public MetricGroup merge(MetricGroup another) {
this.uploadedDocs += another.uploadedDocs;
this.uploadedKbs += another.uploadedKbs;
return this;
}
然后,您可以使用Collectors.toMap
按应用程序对指标进行分组:
Map<String, MetricGroup> result = Stream.of(
new MetricGroup("app1", 1,100),
new MetricGroup("app1", 1,300),
new MetricGroup("app2", 1,200))
.collect(Collectors.toMap(
MetricGroup::getApplication,
MetricGroup::new, // use copy constructor
MetricGroup::merge)); // use MetricGroup.merge method
请注意,我们需要使用复制构造函数来不使流的原始MetricGroup
元素发生变异。
答案 2 :(得分:1)
您可以尝试类似的事情
private static final List<MetricGroup> mgArr = Arrays.asList(new MetricGroup("app1", 1,100),new MetricGroup("app1", 1,300),new MetricGroup("app2", 1,200));
Map<String, Long> groupedByAppKbs = mgArr.stream()
.collect(groupingBy(MetricGroup::getApplication, summingLong(MetricGroup::getUploadedKbs)));
比访问变量更重要:
groupedByAppKbs.get("app1").longValue();
答案 3 :(得分:1)
在按Collectors.reducing
分组时使用MetricGroup.application
:
Map<String, MetricGroup> collect =
source.stream()
.collect(
groupingBy(MetricGroup::getApplication,
reducing(new MetricGroup(null, 0, 0),
(m1, m2) -> new MetricGroup(
m2.application,
m1.getUploadedDocs() + m2.getUploadedDocs(),
m1.getUploadedKbs() + m2.getUploadedKbs()))));