Странная группа методов "уменьшить" в библиотеке операций сбора данных JDK8

Почему новый класс JDK8 Stream содержит только следующие методы reduce:

T reduce(BinaryOperator<T> reducer)
T reduce(T identity, BinaryOperator<T> reducer)
U reduce(U identity, BiFunction<U, ? super T, U> reducer, 
    BinaryOperator<U> combiner)

но не очевидный метод, который соответствует функциям reduce/fold, найденным на других языках (например, Haskell foldl :: (a -> b -> a) -> a -> [b] -> a) и который может выглядеть следующим образом:

U reduce(U identity, BiFunction<U, ? super T, U> reducer)

?

Вместо этого существует аналогичный метод с дополнительным аргументом combiner. Я даже не уверен, как его использовать, поскольку документация API, связанная с выше, не использует этот аргумент в этом примере, она только упоминает его требуемые свойства.

Почему методы JDK8 сделаны так и как я могу имитировать стандартное поведение fold с ними?

Ответ 1

Операции с параллельными данными reduce служат в качестве общих операций агрегации значений над набором данных (например, массивом элементов). Вы можете использовать их для реализации, например, суммы.

Порядок, в котором значения набора данных объединены вместе (например, суммированы), не указан, поэтому они не соответствуют foldl, найденным в Haskell или reduceLeft/foldLeft, найденным в Scala.

Дополнительный аргумент combiner в третьей строке используется, когда тип результата агрегации отличается от типа ваших элементов. В этих случаях вам нужно указать, как объединить два результата вместе. Допустим, вы хотите реализовать количество гласных в строке, используя третье сокращение. Элементы данных являются символами, а reducer указывает, как сочетаются символ и текущий счетчик:

(Integer count, Character c) -> if (isVowel(c)) count + 1 else count

Объединитель будет просто суммой:

(Integer count1, Integer count2) -> count1 + count2

Scala Parallel Collections, например, имеет эти для а теперь (найдите aggregate).