Java 8 Streams: когда использовать collect() или reduce()
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Если требуется собрать элементы потока в такие коллекции, как List
, Set
или Map
, ваш выбор – collect
. Вам помогут методы класса Collectors
:
List<String> собраноВместе = поток.collect(Collectors.toList());
Это похоже на приручение дикого единорога.
А когда вам нужно преобразовать элементы потока в один итоговый результат, лучше использовать reduce
. Он идеален для вычисления сумм, нахождения минимума или максимума, а также для конкатенации строк:
String объединенноеСоответствие = поток.reduce("", String::concat);
Такое сочетание напоминает смешивание идеального коктейля.
Лёгкое усвоение: Как использовать collect
Метод collect
собирает элементы с помощью изменяемого контейнера, например, ArrayList
или StringBuilder
. Важны следующие моменты:
- Потокобезопасность: При параллельной обработке
collect()
обеспечивает безопасность, используя изолированные от потоков контейнеры. - Специальные Накопители:
Collectors
предоставляет готовые решения для группирования, разделения данных и подведения итогов. - Повышенная производительность со строками:
С использованиемStringBuilder
иcollect()
вам не придется беспокоиться о расходе памяти и можно будет наслаждаться высокой скоростью обработки.
String бойкийРезультат = поток.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString();
Переворачиваем монету: Где использовать reduce
reduce
подходит для работы с неизменяемыми объектами и для выполнения операций, требующих создания новых значений, например, в арифметических вычислениях.
- Немутабельное Сокращение: Например, точный расчёт с помощью
BigDecimal
. - Последовательная Обработка: Если вам подходят последовательные потоки, выбирайте
reduce
. - Бинарные Операции: Применяйте
reduce
, когда результат и элементы потока имеют один и тот же тип.
int сумма = поток.reduce(0, Integer::sum);
Так числа могут сосуществовать в гармонии.
Удваиваем ставки: Продвинутые приёмы и соображения
Здесь несколько советов для опытных разработчиков.
Создание Пользовательских Коллекторов
Если встроенных Collectors
вам не хватает, создайте свой Collector
для точного контроля над процессом:
Collector<Widget, ?, TreeSet<Widget>> вНабор =
Collector.of(TreeSet::new, TreeSet::add,
(left, right) -> { left.addAll(right); return left; });
Сочетание Коллекторов: Высший уровень мастерства
Скомбинируйте Collectors
, чтобы создать комплексные структуры данных:
Map<Integer, List<String>> группировкаПоДлине =
поток.collect(Collectors.groupingBy(String::length, Collectors.toList()));
Навигация по параллельным потокам с помощью reduce
Для эффективной параллельной обработки убедитесь, что ваш бинарный оператор ассоциативен и коммутативен. Это поможет избежать ошибок при параллельной обработке данных.
Соображения о производительности
Следует помнить, что при использовании reduce
частое создание объектов может негативно сказаться на производительности.
Визуализация
Техника | Кухонный Инструмент | Результат Блюда |
---|---|---|
collect | 🍽 Поднос Для Подачи | 🌟 Изысканное Блюдо |
reduce | 🔪 Поварской Нож | 💪 Концентрированный Вкус |
collect
идеально подходит для формирования сложных и изысканных коллекций:
поток().collect(Collectors.toList());
reduce
позволяет комбинировать элементы в компактные и мощные структуры:
поток().reduce((a, b) -> a + b);
Параллельные потоки и их особенности
collect с Параллельными Потоками
Благодаря способности collect
эффективно управлять конкуренцией, его можно использовать и с параллельными потоками. Однако иногда это может привести к небольшому ухудшению производительности.
List<String> параллельноСобрано = поток.parallel().collect(Collectors.toList());
reduce в Параллельной Вселенной
reduce
может работать без синхронизации при выполнении простых задач, что благотворно влияет на производительность. Однако следует пристально контролировать работу бинарного оператора при использовании параллельных потоков.
int параллельнаяСумма = поток.parallel().reduce(0, Integer::sum);
Полезные материалы
- Collectors (Java Platform SE 8 ) — официальная документация Java, посвященная классу Collector.
- Stream (Java Platform SE 8 ) — документация Java, раскрывающая детали исполнения метода
reduce
. - Java 8 Streams – collect vs reduce – Stack Overflow — обсуждение на Stack Overflow с примерами применения collect и reduce.
- Reduction (The Java™ Tutorials > Collections > Aggregate Operations) — учебное пособие Oracle, раскрывающее тему операций сокращения потоков в Java.