Normalna redukcja ma na celu połączenie dwóch niezmiennych wartości, takich jak int, double itp., I utworzenie nowej; to niezmienna redukcja. W przeciwieństwie do tego metoda zbierania została zaprojektowana w celu zmutowania pojemnika w celu zgromadzenia wyniku, który ma przynieść.
Aby zilustrować problem, załóżmy, że chcesz osiągnąć Collectors.toList()
za pomocą prostej redukcji, takiej jak
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;
});
To jest odpowiednik Collectors.toList()
. Jednak w tym przypadku modyfikujesz plik List<Integer>
. Jak wiemy ArrayList
, nie jest bezpieczny dla wątków, ani nie można bezpiecznie dodawać / usuwać z niego wartości podczas iteracji, więc otrzymasz wyjątek współbieżny ArrayIndexOutOfBoundsException
lub dowolny inny wyjątek (szczególnie gdy jest uruchamiany równolegle) podczas aktualizowania listy lub sumatora próbuje scalić listy, ponieważ modyfikujesz listę przez gromadzenie (dodawanie) do niej liczb całkowitych. Jeśli chcesz, aby ten wątek był bezpieczny, musisz za każdym razem przekazywać nową listę, która wpłynie negatywnie na wydajność.
Natomiast Collectors.toList()
działa w podobny sposób. Jednak gwarantuje bezpieczeństwo wątków, gdy gromadzisz wartości na liście. Z dokumentacji collect
metody :
Wykonuje mutowalną operację redukcji na elementach tego strumienia przy użyciu Collectora. Jeśli strumień jest równoległy, a moduł zbierający jest współbieżny, a strumień jest nieuporządkowany lub kolektor jest nieuporządkowany, zostanie przeprowadzona współbieżna redukcja. W przypadku wykonywania równoległego można utworzyć wystąpienie, zapełnić i scalić wiele wyników pośrednich, aby zachować izolację zmiennych struktur danych. Dlatego nawet w przypadku wykonywania równolegle ze strukturami danych, które nie są bezpieczne dla wątków (takimi jak ArrayList), nie jest wymagana dodatkowa synchronizacja do równoległej redukcji.
Więc odpowiadając na twoje pytanie:
Kiedy użyjesz collect()
vs reduce()
?
jeśli mają wartości niezmienne, takie jak ints
, doubles
, Strings
działa wtedy normalnie redukcja dobrze. Jednakże, jeśli masz do reduce
swoich wartości powiedzmy a List
(zmienna struktura danych), musisz użyć mutowalnej redukcji z tą collect
metodą.