La riduzione normale ha lo scopo di combinare due valori immutabili come int, double, ecc. E produrne uno nuovo; è una riduzione immutabile . Al contrario, il metodo di raccolta è progettato per mutare un contenitore per accumulare il risultato che dovrebbe produrre.
Per illustrare il problema, supponiamo che tu voglia ottenere Collectors.toList()
usando una semplice riduzione come
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;
});
Questo è l'equivalente di Collectors.toList()
. Tuttavia, in questo caso muti il List<Integer>
. Come sappiamo, ArrayList
non è thread-safe, né è possibile aggiungere / rimuovere valori da esso durante l'iterazione, in modo da ottenere un'eccezione simultanea ArrayIndexOutOfBoundsException
o qualsiasi tipo di eccezione (specialmente se eseguita in parallelo) quando si aggiorna l'elenco o il combinatore cerca di unire gli elenchi perché stai mutando l'elenco accumulando (aggiungendo) i numeri interi ad esso. Se vuoi rendere questo thread sicuro, devi passare ogni volta un nuovo elenco che comprometterebbe le prestazioni.
Al contrario, le Collectors.toList()
opere funzionano in modo simile. Tuttavia, garantisce la sicurezza del thread quando si accumulano i valori nell'elenco. Dalla documentazione per il collect
metodo :
Esegue un'operazione di riduzione mutabile sugli elementi di questo flusso utilizzando un servizio di raccolta. Se il flusso è parallelo e Collector è simultaneo e il flusso non è ordinato o il collector non è ordinato, verrà eseguita una riduzione simultanea. Se eseguiti in parallelo, è possibile creare istanze, compilare e unire più risultati intermedi in modo da mantenere l'isolamento delle strutture di dati mutabili. Pertanto, anche se eseguito in parallelo con strutture dati non thread-safe (come ArrayList), non è necessaria alcuna sincronizzazione aggiuntiva per una riduzione parallela.
Quindi per rispondere alla tua domanda:
Quando useresti collect()
vs reduce()
?
se si dispone di valori immutabili, come ints
, doubles
, Strings
quindi riduzione normale funziona bene. Tuttavia, se devi dire i reduce
tuoi valori in una List
(struttura di dati mutabili), allora devi usare la riduzione mutabile con il collect
metodo.