Нормальне зменшення має на увазі поєднання двох незмінних значень, таких як int, double та ін. Та отримання нового; це незмінне зменшення. На відміну від цього, метод збирання призначений для мутації контейнера для накопичення результату, який він повинен отримати.
Щоб проілюструвати проблему, припустимо, що ви хочете досягти, Collectors.toList()використовуючи просте скорочення типу
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;
});
Це еквівалент Collectors.toList(). Однак у цьому випадку ви мутуєте List<Integer>. Як ми знаємо, ArrayListце не безпечно для потоків, і не безпечно додавати / видаляти значення з нього під час ітерації, тож ви отримаєте одночасне виключення ArrayIndexOutOfBoundsExceptionабо будь-який виняток (особливо при паралельному виконанні), коли ви оновлюєте список або комбінатор намагається об'єднати списки, оскільки ви мутуєте список, накопичуючи (додаючи) цілі числа до нього. Якщо ви хочете зробити цей потік безпечним, вам потрібно кожного разу переходити новий список, що може погіршити продуктивність.
На відміну від цього, Collectors.toList()твори аналогічно. Однак це гарантує безпеку потоку під час накопичення значень у списку. З документації щодо collectспособу :
Виконує операцію скорочення змінних елементів цього потоку за допомогою колектора. Якщо потік паралельний, а колектор паралельний, або потік не упорядкований, або колектор не упорядкований, тоді буде здійснено одночасне зменшення. При паралельному виконанні декілька проміжних результатів можуть бути інстанційними, заселеними та об'єднаними, щоб підтримувати ізоляцію змінних структур даних. Тому навіть при виконанні паралельно зі структурами даних, що не є безпечними для потоків (такими як ArrayList), додаткова синхронізація не потрібна для паралельного скорочення.
Отже, щоб відповісти на ваше запитання:
Коли ви використовуєте collect()vs reduce()?
якщо у вас є непорушні цінності , такі як ints, doubles, Stringsто нормальне зниження працює просто відмінно. Однак, якщо вам потрібно вказати reduceсвої значення List(структура даних, що змінюється), тоді вам потрібно використовувати зменшення змінних за допомогою collectметоду.