Ответ
Метод reduce() в Stream API используется для свертки элементов потока в одно итоговое значение с помощью ассоциативной функции.
Основные формы:
Optional<T> reduce(BinaryOperator<T> accumulator)T reduce(T identity, BinaryOperator<T> accumulator)U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
Примеры:
-
Суммирование чисел (с identity):
List<Integer> numbers = List.of(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, (a, b) -> a + b); // Идентичность 0 гарантирует результат int, а не Optional System.out.println(sum); // 15Или с методом-ссылкой:
int sum = numbers.stream() .reduce(0, Integer::sum); -
Поиск максимального значения (без identity):
Optional<Integer> max = numbers.stream() .reduce(Integer::max); max.ifPresent(System.out::println); // 5 -
Конкатенация строк:
List<String> words = List.of("Hello", " ", "World", "!"); String sentence = words.stream() .reduce("", String::concat); System.out.println(sentence); // "Hello World!"
Важно: Функция-аккумулятор должна быть ассоциативной, чтобы корректно работать в параллельных потоках.
Ответ 18+ 🔞
Слушай, а вот этот ваш reduce() в стримах — это ж такая, блядь, классическая свертка, как в функциональщине! Берёшь кучу элементов и плющишь их в одно-единственное значение, как будто хуй с горы скатился и всё на своём пути собрал.
Смотри, какие у него три основные позы есть:
Optional<T> reduce(BinaryOperator<T> accumulator)— начнём без начального значения, на авось, поэтому результат вOptionalзаворачивают, а то вдруг поток пустой, и нихуя не получится.T reduce(T identity, BinaryOperator<T> accumulator)— тут уже даём стартовое значение (identity), и тогда даже из пустого потока вылезет эта самаяidentity. Удобно, блядь.U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)— это уже для продвинутых, когда тип результата отличается от типа элементов. Третий аргумент (combiner) — для параллельных стримов, чтобы куски склеивать, но в последовательных его обычно игнорят, ёпта.
Ну и примеры, чтобы не быть пиздаболом:
-
Чисто сложить все цифры (со стартовым нулём):
List<Integer> numbers = List.of(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, (a, b) -> a + b); // Берём ноль и начинаем накручивать System.out.println(sum); // 15А можно и покрасивее, через ссылку на метод:
int sum = numbers.stream() .reduce(0, Integer::sum); // Та же хуйня, только компактнее -
Найти максимум (без начального значения, на свой страх и риск):
Optional<Integer> max = numbers.stream() .reduce(Integer::max); // А вдруг пустой список? Optional нас спасает! max.ifPresent(System.out::println); // 5 -
Склеить строки в одну:
List<String> words = List.of("Hello", " ", "World", "!"); String sentence = words.stream() .reduce("", String::concat); // Берём пустую строку и прилепляем к ней всё подряд System.out.println(sentence); // "Hello World!"
И главное, блядь, запомни: функция-аккумулятор должна быть ассоциативной! То есть (a + b) + c должно равняться a + (b + c). Иначе в параллельных стримах начнётся такой пиздец и рассинхрон, что мало не покажется.