Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

249
Views
Java 8 stream.collect (... groupingBy (... mapeo (... reduce))) reduce el uso de BinaryOperator

Jugué con una solución usando groupingBy , mapping y reducing a la siguiente pregunta: Cree elegantemente un mapa con campos de objetos como clave/valor de flujo de objetos en Java 8 . Resumiendo, el objetivo era conseguir un mapa con la edad como clave y las aficiones de una persona como Set .

Una de las soluciones que se me ocurrió (no es agradable, pero ese no es el punto) tenía un comportamiento extraño.

Con la siguiente lista como entrada:

 List<Person> personList = Arrays.asList( new Person(/* name */ "A", /* age */ 23, /* hobbies */ asList("a")), new Person("BC", 24, asList("b", "c")), new Person("D", 23, asList("d")), new Person("E", 23, asList("e")) );

y la siguiente solución:

 Collector<List<String>, ?, Set<String>> listToSetReducer = Collectors.reducing(new HashSet<>(), HashSet::new, (strings, strings2) -> { strings.addAll(strings2); return strings; }); Map<Integer, Set<String>> map = personList.stream() .collect(Collectors.groupingBy(o -> o.age, Collectors.mapping(o -> o.hobbies, listToSetReducer))); System.out.println("map = " + map);

Obtuve:

 map = {23=[a, b, c, d, e], 24=[a, b, c, d, e]}

claramente no es lo que esperaba. Más bien esperaba esto:

 map = {23=[a, d, e], 24=[b, c]}

Ahora, si solo reemplazo el orden de (strings, strings2) del operador binario (del colector reductor) a (strings2, strings) obtengo el resultado esperado. Entonces, ¿qué me perdí aquí? ¿Interpreté mal el colector reducing ? ¿O qué parte de la documentación me perdí que hace evidente que mi uso no estaba funcionando como se esperaba?

La versión de Java es 1.8.0_121 si eso importa.

about 4 years ago · Santiago Trujillo
1 answers
Answer question

0

La reducción nunca debe modificar los objetos entrantes. En su caso, está modificando el HashSet entrante que se supone que es el valor de identidad y lo devuelve, por lo que todos los grupos tendrán como resultado la misma instancia de HashSet , que contiene todos los valores.

Lo que necesita es una Reducción mutable , que se puede implementar a través de Collector.of(…) como si ya se hubiera implementado con los recopiladores prediseñados Collectors.toList() , Collectors.toSet() , etc.

 Map<Integer, Set<String>> map = personList.stream() .collect(Collectors.groupingBy(o -> o.age, Collector.of(HashSet::new, (s,p) -> s.addAll(p.hobbies), (s1,s2) -> { s1.addAll(s2); return s1; })));

La razón por la que necesitamos un recopilador personalizado es que Java 8 no tiene el recopilador flatMapping , que Java 9 va a presentar. Con eso, la solución se verá así:

 Map<Integer, Set<String>> map = personList.stream() .collect(Collectors.groupingBy(o -> o.age, Collectors.flatMapping(p -> p.hobbies.stream(), Collectors.toSet())));
about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!