Java 8 stream.collect (… groupingBy (… mapping (… redução))) reduzindo o uso de BinaryOperator
Eu brinquei com uma solução usandogroupingBy
, mapping
ereducing
para a seguinte pergunta:Crie de forma elegante o mapa com campos de objetos como chave / valor do fluxo de objetos em Java 8. Resumiu o objetivo era obter um mapa com a idade como chave e os hobbies de uma pessoa comoSet
.
Uma das soluções que eu encontrei (não é legal, mas não é esse o ponto) teve um comportamento estranho.
Com a seguinte 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"))
);
e a seguinte solução:
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);
Eu tenho:
map = {23=[a, b, c, d, e], 24=[a, b, c, d, e]}
claramente não era o que eu estava esperando. Eu esperava isso:
map = {23=[a, d, e], 24=[b, c]}
Agora, se eu apenas substituir a ordem de(strings, strings2)
do operador binário (do coletor redutor) para(strings2, strings)
Eu recebo o resultado esperado. Então, o que eu perdi aqui? Eu interpretei mal oreducing
-colecionador? Ou qual a documentação que perdi que torna óbvio que meu uso não estava funcionando conforme o esperado?
A versão Java é 1.8.0_121, se isso importa.