Tengo una lista de tipos List<A>
y con la operación de mapa obtengo una lista colectiva de tipos List<B>
para todos los elementos A fusionados en una lista.
List<A> listofA = [A1, A2, A3, A4, A5, ...]
List<B> listofB = listofA.stream()
.map(a -> repo.getListofB(a))
.flatMap(Collection::stream)
.collect(Collectors.toList());
sin plano
List<List<B>> listOflistofB = listofA.stream()
.map(a -> repo.getListofB(a))
.collect(Collectors.toList());
Quiero recopilar los resultados como un mapa de tipo Map<A, List<B>>
y hasta ahora intentar con varias opciones Collectors.toMap
u Collectors.groupingBy
opciones, pero no puedo obtener el resultado deseado.
java
lambda
java-8
java-stream
collectors
Amitoj
fuente
fuente
A
elementos repetidos en tuList<A>
?Respuestas:
Puede usar el
toMap
recopilador con una referencia de método acotado para obtener lo que necesita. Observe también que esta solución asume que no tiene instancias A repetidas en su contenedor fuente. Si esa precondición mantiene esta solución, obtendría el resultado deseado. Así es como se ve.Si tiene elementos A duplicados, debe usar esta función de combinación además de lo que se proporciona anteriormente. La función de fusión se ocupa de conflictos clave, si los hay.
Y aquí hay un enfoque Java9 mucho más sucinto que utiliza el
flatMapping
recopilador para manejar elementos A repetidos.fuente
Sería sencillo
fuente
Para recopilar un
Map
donde las claves son losA
objetos sin cambios, y los valores son la lista deB
objetos correspondientes , puede reemplazar eltoList()
recopilador por el siguiente recopilador:El primer argumento define cómo calcular la clave del objeto original:
identity()
toma el objeto original de la secuencia sin cambios.El segundo argumento define cómo se calcula el valor , por lo que aquí solo consiste en una llamada a su método que transforma
A
a una lista deB
.Dado que el
repo
método solo toma un parámetro, también puede mejorar la claridad reemplazando el lambda con una referencia de método:fuente
En esta respuesta, estoy mostrando lo que sucede si tienes
A
elementos repetidos en tuList<A> listofA
lista.En realidad, si hubiera duplicados
listofA
, el siguiente código arrojaría unIllegalStateException
:La excepción podría ser lanzada porque
Collectors.toMap
no sabe cómo fusionar valores cuando hay una colisión en las teclas (es decir, cuando la función del mapeador de teclas devuelve duplicados, como sería el casoFunction.identity()
si hubiera elementos repetidos en lalistofA
lista).Esto se afirma claramente en los documentos :
Los documentos también nos dan la solución: en caso de que haya elementos repetidos, debemos proporcionar una forma de fusionar valores. Aquí hay una de esas formas:
Esto usa la versión sobrecargada
Collectors.toMap
que acepta una función de fusión como su tercer argumento. Dentro de la función de fusión,Collection.addAll
se está utilizando para agregar losB
elementos de cadaA
elemento repetido en una lista única para cada unoA
.En la función del mapeador de valores,
ArrayList
se crea un nuevo , de modo que el originalList<B>
de cada unoA
no está mutado. Además, como estamos creando unArraylist
, sabemos de antemano que puede ser mutado (es decir, podemos agregarle elementos más adelante, en caso de que haya duplicadoslistofA
).fuente