doblemc
Estoy tratando de agrupar por (para mapear) y luego transformar la lista de valores en una lista diferente.
Tengo una lista de documentos del distrito:
List<DistrictDocument> docs = new ArrayList<>();
Luego lo transmito y lo agrupo por ciudad:
Map<String, List<DistrictDocument>> collect = docs.stream()
.collect(Collectors.groupingBy(DistrictDocument::getCity));
También tengo un método que toma DistrictDocument y crea Slugable a partir de él:
private Fizz createFizz(DistrictDocument doc) {
return new Fizz().name(doc.getName()).fizz(doc.getFizz());
}
¿Hay alguna manera de poner ese método en mi transmisión anterior para obtener Map<String, List<Fizz>>
? Intenté agregar el segundo argumento a groupingBy pero no pude encontrar una forma adecuada y siempre recibía errores de compilación.
Editar: ¿Qué pasa si mi createFizz regresa? List<Fizz>
? ¿Hay alguna opción para aplanar esta lista en Collectors.mapping porque todavía quiero tener Map<String, List<Fizz>>
en lugar de Map<String, List<List<Fizz>>>
Eran
Tienes que encadenar un Collectors.mapping()
coleccionista a la Collectors.groupingBy()
coleccionista:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.groupingBy(DistrictDocument::getCity,
Collectors.mapping(d->createFizz(d),Collectors.toList())));
Si createFizz(d)
devolvería un List<Fizz
puede aplanarlo usando Java 9 Collectors.flatMapping
:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.groupingBy(DistrictDocument::getCity,
Collectors.flatMapping(d->createFizz(d).stream(),Collectors.toList())));
Si no puede usar Java 9, tal vez usando Collectors.toMap
ayudará:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.toMap(DistrictDocument::getCity,
d->createFizz(d),
(l1,l2)->{l1.addAll(l2);return l1;}));
-
d->createFizz(d)
Puede usar una referencia de método para esto. Es cierto que no conocemos la clase.– Miguel
28 de febrero de 2018 a las 12:25
-
@Michael sí, no saber la clase fue la razón principal por la que no usé una referencia de método.
– Eran
28 de febrero de 2018 a las 12:26
-
¿Podrías revisar mi edición? Desafortunadamente, createFizz tiene que devolver List
y parece que no puedo encontrar una manera de aplanar esta lista. – doblemc
28 de febrero de 2018 a las 12:40
-
@doublemc Creo que java 9 tiene Collectors.flatMapping, así que puedes escribir
Collectors.flatMapping(d->createFizz(d).stream(),Collectors.toList())))
;– Eran
28 de febrero de 2018 a las 12:41
-
¿Qué pasa si solo puedo usar hasta Java 8? ¿Alguna opción para hacer eso?
– doblemc
28 de febrero de 2018 a las 12:43
En caso de que desee hacer una agrupación doblemente anidada:
Digamos que tienes una colección de EducationData
objetos que contienen el nombre de la escuela, el nombre del profesor y el nombre del alumno. Pero quieres un mapa anidado que se parezca a:
Que tienes
class EducationData {
String school;
String teacher;
String student;
// getters setters ...
}
Lo que quieras
Map<String, Map<String, List<String>>> desiredMapOfMpas ...
// which would look like this :
"East High School" : {
"Ms. Jackson" : ["Derek Shepherd", "Meredith Grey", ...],
"Mr. Teresa" : ["Eleanor Shellstrop", "Jason Mendoza", ...],
....
}
Cómo llegar allá
import static java.util.stream.Collectors.*;
public doubleNestedGroup(List<EducationData> educations) {
Map<String, Map<String, List<String>>> nestedMap = educations.stream()
.collect(
groupingBy(
EducationData::getSchool,
groupingBy(
EducationData::getTeacher,
mapping(
EducationData::getStudent,
toList()
)
)
)
);
}