Strange "reduce" method group in JDK8 bulk collection operations library

collections, java, java-8, lambda

Solution

The `reduce`-like data-parallel operations serve as general value-aggregation operations over a data set (e.g. an array of elements). You can use them to implement, for example, the sum.

The order in which the values of the data set are combined together (e.g. summed) is not specified, so they do not correspond to `foldl` found in Haskell or `reduceLeft`/`foldLeft` found in Scala.

The extra `combiner` argument in the third line is used when the result type of the aggregation is different than the type of your elements. In these cases you have to specify how to combine two results together. Lets say you want to implement a count of vowels in a string using the third reduce. The data elements are characters and the `reducer` specifies how a character and the current count are combined:

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

The combiner will just be a sum:

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

Scala Parallel Collections, for example, has these for a while now (search for `aggregate`).

Problem

Why does the new JDK8 `Stream` class contain only the following `reduce` methods: ``` 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) ``` but not an obvious method which corresponds to `reduce`/`fold` functions found in other languages (e.g. Haskell `foldl :: (a -> b -> a) -> a -> [b] -> a`) and which could look like this: ``` U reduce(U identity, BiFunction<U, ? super T, U> reducer) ``` ? Instead there is a similar method which has an extra `combiner` argument. I'm not even sure how to use it since the API documentation I linked to above does not use this argument in the example, it only mentions its required properties. Why are the JDK8 methods made like this, and how can I emulate standard `fold` behavior with them?

Original source