Regrouper par imbriqué (multi-niveaux) dans Java 8
Le besoin se fait souvent sentir d'effectuer un regroupement d'objets à plusieurs niveaux en fonction de plusieurs clés . Dans ce cas, nous avons un ensemble de classes représentant des données impliquant une liste d'éléments avec une clé et une liste de sous-éléments, également avec une clé. L'objectif est de regrouper les éléments par leur clé et, pour chaque agrégation, de regrouper davantage les sous-éléments par leur clé, ce qui donne lieu à une carte imbriquée.
En utilisant Collectors.groupingBy de Java 8, nous pouvons y parvenir en employant une combinaison de flatMap et un collecteur de mappage plat personnalisé. Nous commençons par créer une paire temporaire à l'aide de Stream.flatMap pour contenir les combinaisons d'éléments et de sous-éléments.
<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>
Alternativement, nous pouvons éviter de créer des objets temporaires en utilisant un collecteur de mappage plat, qui ne sera malheureusement pas disponible jusqu'à Java 9. Avec cette approche, le code se simplifie comme suit :
<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>
Pour les utilisateurs qui ne souhaitent pas attendre Java 9, un collecteur de mappage plat personnalisé peut être implémenté :
<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>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!