Nested (Multi Level) Group By in Java 8
The need often arises to perform multi-level grouping of objects based on multiple keys. In this case, we have a set of classes representing data involving a list of items with a key and a list of subitems, also with a key. The goal is to group the items by their key and for each aggregation, further group the subitems by their key, resulting in a nested map.
Using Java 8's Collectors.groupingBy, we can achieve this by employing a combination of flatMap and a custom flat-mapping collector. We start by creating a temporary pair using Stream.flatMap to hold the combinations of items and subitems.
<code class="java">Map<T, Map<V, List<SubItem>>> result = pojo.getItems().stream() .flatMap(item -> item.subItems.stream() .map(sub -> new AbstractMap.SimpleImmutableEntry<>(item.getKey1(), sub))) .collect(Collectors.groupingBy(AbstractMap.SimpleImmutableEntry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.groupingBy(SubItem::getKey2))));</code>
Alternatively, we can avoid creating temporary objects by using a flat-mapping collector, which unfortunately will not be available until Java 9. With this approach, the code simplifies to:
<code class="java">Map<T, Map<V, List<SubItem>>> result = pojo.getItems().stream() .collect(Collectors.groupingBy(Item::getKey1, Collectors.flatMapping(item -> item.getSubItems().stream(), Collectors.groupingBy(SubItem::getKey2))));</code>
For users who may not want to wait for Java 9, a custom flat-mapping collector can be implemented:
<code class="java">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> acc = downstream.accumulator(); return Collector.of(downstream.supplier(), (a, t) -> { try(Stream<? extends U> s=mapper.apply(t)) { if(s!=null) s.forEachOrdered(u -> acc.accept(a, u)); }}, downstream.combiner(), downstream.finisher(), downstream.characteristics().toArray(new Collector.Characteristics[0])); }</code>
The above is the detailed content of How to Implement Nested Grouping in Java Using Collectors.groupingBy in Java 8?. For more information, please follow other related articles on the PHP Chinese website!