1 回答
TA贡献1789条经验 获得超10个赞
如果你有使用 Java9 的自由,我建议你使用flatMapping收集器来完成这件事。这是它的样子。
Map<String, Double> avgWeightByBuildingName = buildings.stream()
.collect(Collectors.groupingBy(Building::getName,
Collectors.flatMapping(b -> b.getAnimals().stream(),
Collectors.averagingDouble(Animal::getWeight))));
然而,这里的 java8 解决方案与前者相比看起来有点冗长。
Map<String, Double> avgWeightByBuildingName = buildings.stream()
.flatMap(b -> b.getAnimals().stream()
.map(a -> new AbstractMap.SimpleEntry<>(b.getName(), a.getWeight())))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.averagingDouble(Map.Entry::getValue)));
flatMapping或者考虑按照此答案编写您自己的收集器。这是我在查看上述答案和 JDK 9 源代码后想出的一个这样的实现。
static <T, U, A, R> Collector<T, ?, R> flatMapping(Function<? super T,
? extends Stream<? extends U>> mapper, Collector<? super U, A, R> downstream) {
BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
return Collector.of(downstream.supplier(), (r, t) -> {
try (Stream<? extends U> result = mapper.apply(t)) {
result.sequential().forEach(u -> downstreamAccumulator.accept(r, u));
}
}, downstream.combiner(), downstream.finisher(),
downstream.characteristics().toArray(new Characteristics[0]));
}
此外,如以下评论所述,这对于较新的 Java 版本有一个直接的迁移策略。
添加回答
举报