如何使用java 8 stream和lambda来flatMap一个groupingBy结果
我有一个包含其他对象列表的对象,我想返回由容器的某些属性映射的包含对象的平面图。 任何一个如果可能只使用流和lambdas?
public class Selling{ String clientName; double total; List products; } public class Product{ String name; String value; }
让我们来处理一系列操作:
List operations = new ArrayList(); operations.stream() .filter(s -> s.getTotal > 10) .collect(groupingBy(Selling::getClientName, mapping(Selling::getProducts, toList());
结果将是善意的
Map<String, List<List>>
但我想像它一样扁平化
Map<String, List>
你可以尝试类似的东西:
Map> res = operations.parallelStream().filter(s -> s.getTotal() > 10) .collect(groupingBy(Selling::getClientName, mapping(Selling::getProducts, Collector.of(ArrayList::new, List::addAll, (x, y) -> { x.addAll(y); return x; }))));
在JDK9中有一个名为flatMapping
的新标准收集器,它可以通过以下方式实现:
public static Collector flatMapping(Function super T, ? extends Stream extends U>> mapper, Collector super U, A, R> downstream) { BiConsumer downstreamAccumulator = downstream.accumulator(); return Collector.of(downstream.supplier(), (r, t) -> { try (Stream extends U> result = mapper.apply(t)) { if (result != null) result.sequential().forEach(u -> downstreamAccumulator.accept(r, u)); } }, downstream.combiner(), downstream.finisher(), downstream.characteristics().toArray(new Collector.Characteristics[0])); }
您可以将其添加到项目中并使用如下:
operations.stream() .filter(s -> s.getTotal() > 10) .collect(groupingBy(Selling::getClientName, flatMapping(s -> s.getProducts().stream(), toList())));