parallel metodos libreria instream ejemplo con collection java java-8 java-stream

metodos - stream java 8 ejemplo



Agrupar por un atributo de Colección utilizando Java Streams (2)

Tengo un objeto que contiene una colección de cadenas, digamos los idiomas que habla una persona.

public class Person { private String name; private int age; private List<String> languagesSpoken; // ... }

Ahora, creando algunas instancias como esta ...

Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German")); Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", "Spanish")); Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German")); //put them in list List<Person> people = Arrays.asList(p1,p2,p3);

... lo que quiero es un Map<String, List<Person>> , para cada idioma que incluya a las personas que hablan el idioma:

["English" -> [p1, p2, p3], "German" -> [p1, p3], etc. ]

Por supuesto, esto se puede programar fácilmente de manera imperativa, pero ¿cómo hacerlo de manera funcional con Java Streams? He intentado algo como people.stream.collect(groupingBy(Person::getLanguagesSpoken)) pero eso, por supuesto, me da un Map<List<String>, List<Person>> . Todos los ejemplos que pude encontrar están usando groupingBy on Primitives o Strings.


Esto también es posible hacerlo sin transmisiones, aún utilizando las nuevas características de java-8.

people.forEach(x -> { x.getLanguagesSpoken().forEach(lang -> { langPersons.computeIfAbsent(lang, ignoreMe -> new ArrayList<>()).add(x); }); });


Puede dividir las instancias de Person en pares de lenguaje y Person (usando flatMap ) y luego agruparlos según sea necesario:

Map<String, List<Person>> langPersons = people.stream() .flatMap(p -> p.getLanguagesSpoken() .stream() .map(l -> new SimpleEntry<>(l,p))) .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList())));