Нормальне зменшення має на увазі поєднання двох незмінних значень, таких як 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
методу.