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, ArrayListnon è thread-safe, né è possibile aggiungere / rimuovere valori da esso durante l'iterazione, in modo da ottenere un'eccezione simultanea ArrayIndexOutOfBoundsExceptiono 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 collectmetodo :
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, Stringsquindi riduzione normale funziona bene. Tuttavia, se devi dire i reducetuoi valori in una List(struttura di dati mutabili), allora devi usare la riduzione mutabile con il collectmetodo.