Agrupación multinivel en Java 8 usando Nested GroupBy
Este artículo explora cómo implementar agrupación multinivel cuando se trata de clases anidadas en Java 8. Específicamente, el objetivo es agrupar elementos por un campo clave1 y luego, para cada grupo de elementos, agruparlos por un campo clave2. En última instancia, el resultado debe ser un mapa con la clave1 como clave externa y un mapa de la clave2 para una lista de subelementos.
El enfoque inicial intenta utilizar el método Collectors.groupingBy para lograr esto, sin embargo, no es posible. No es posible agrupar un solo elemento mediante varias claves directamente. Para superar esto, se utiliza una operación flatMap.
Un método implica crear un par temporal usando Map.entrySet para contener combinaciones de elementos y subelementos antes de recopilarlos. El otro enfoque, disponible en Java 9, aprovecha el recopilador flatMapping, que permite realizar la operación flatMap directamente en el recopilador.
Aquí está la solución flatMap:
Map>> result = pojo.getItems().stream()
.flatMap(item -> item.getSubItems().stream()
.map(sub -> new AbstractMap.SimpleImmutableEntry(item.getKey1(), sub)))
.collect(Collectors.groupingBy(AbstractMap.SimpleImmutableEntry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.groupingBy(SubItem::getKey2))));
Una alternativa que utiliza un recopilador personalizado en Java 8:
static Collector flatMapping(
Function super T,? extends Stream extends U>> mapper,
Collector super U,A,R> downstream) {
BiConsumer 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]));
}
Este recopilador personalizado se puede utilizar de la siguiente manera:
Map>> result = pojo.getItems().stream()
.collect(Collectors.groupingBy(Item::getKey1,
Collectors.flatMapping(item -> item.getSubItems().stream(),
Collectors.groupingBy(SubItem::getKey2))));
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3