Home  >  Article  >  Java  >  How to Implement Nested Grouping in Java Using Collectors.groupingBy in Java 8?

How to Implement Nested Grouping in Java Using Collectors.groupingBy in Java 8?

Barbara Streisand
Barbara StreisandOriginal
2024-10-24 08:54:30163browse

How to Implement Nested Grouping in Java Using Collectors.groupingBy in Java 8?

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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn