A redução normal visa combinar dois valores imutáveis , como int, double, etc. e produzir um novo; é uma redução imutável . Por outro lado, o método de coleta é projetado para alterar um contêiner para acumular o resultado que ele deveria produzir.
Para ilustrar o problema, suponhamos que você queira obter Collectors.toList()
uma redução simples como
List<Integer> numbers = stream.reduce(
new ArrayList<Integer>(),
(List<Integer> l, Integer e) -> {
l.add(e);
return l;
},
(List<Integer> l1, List<Integer> l2) -> {
l1.addAll(l2);
return l1;
});
Isso é equivalente a Collectors.toList()
. No entanto, neste caso, você modifica o List<Integer>
. Como sabemos que ArrayList
não é seguro para threads, nem é seguro adicionar / remover valores dele durante a iteração, para que você receba uma exceção simultânea ArrayIndexOutOfBoundsException
ou qualquer outro tipo de exceção (especialmente quando executado em paralelo) ao atualizar a lista ou o combinador tenta mesclar as listas porque você está mudando a lista acumulando (adicionando) os números inteiros a ela. Se você deseja tornar esse thread seguro, precisará passar uma nova lista sempre que prejudicar o desempenho.
Por outro lado, os Collectors.toList()
trabalhos de maneira semelhante. No entanto, garante a segurança do encadeamento quando você acumula os valores na lista. Na documentação do collect
método :
Executa uma operação de redução mutável nos elementos desse fluxo usando um Coletor. Se o fluxo for paralelo e o Coletor for simultâneo, ou o fluxo não estiver ordenado ou o coletor não estiver ordenado, será executada uma redução simultânea. Quando executados em paralelo, vários resultados intermediários podem ser instanciados, preenchidos e mesclados para manter o isolamento de estruturas de dados mutáveis. Portanto, mesmo quando executado em paralelo com estruturas de dados não thread-safe (como ArrayList), nenhuma sincronização adicional é necessária para uma redução paralela.
Então, para responder sua pergunta:
Quando você usaria collect()
vs reduce()
?
se você tiver valores imutáveis, como ints
, doubles
, Strings
redução que o normal funciona muito bem. No entanto, se você tiver que reduce
digitar seus valores a List
(estrutura de dados mutáveis), precisará usar a redução mutável com o collect
método