Reducing reduce

Brian Goetz brian.goetz at
Mon Feb 11 08:41:33 PST 2013

Now that we've added all the shapes of map() to Stream (map to 
ref/int/long/double), and we've separated functional reduce (currently 
called reduce) from mutable reduce (currently called collect), I think 
that leaves room for taking out one of the reduce methods from Stream:

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

This is the one that confuses everyone anyway, and I don't think we need 
it any more.

The argument for having this form instead of discrete map+reduce are:
  - fused map+reduce reduces boxing
  - this three-arg form can also fold filtering into the accumulation

However, since we now have primitive-bearing map methods, and we can do 
filtering before and after the map, is this form really carrying its 
weight?  Specifically because people find it counterintuitive, we should 
consider dropping it and guiding people towards map+reduce.

For example, "sum of pages" over a stream of Documents is better written as:

rather than

   docs.reduce(0, (count, d) -> count + d.getPageCount(), Integer::sum)

The big place where we need three-arg reduce is when we're folding into 
a mutable store.  But that's now handled by collect().

Have I missed any use cases that would justify keeping this form?

More information about the lambda-libs-spec-observers mailing list