DEV Community

Mariano
Mariano

Posted on

Java: Nesting functions with Stream Reduce

Java: Nesting Functions with Stream Reduce

One of the less known stream operators is Reduce. I've studyied Haskell during University and reduce strongly reminds of Haskell's function fold.

What is reduce ?

Given a list of elements and a function (aka accumulator), get a single resulting value.
The easy example: make the sum of a list of Integers.
Integer result = Stream.of(1, 2, 3, 4, 5).reduce(0, (a, b) -> a + b);
That will make: 1+2+3+4+5+0

However, Streams api already solves that:
Integer result = IntStream.of(1, 2, 3, 4, 5).sum();

Composite functions with Reduce

Suppose we have a list of functions and we want to build a function which contains all the ones from the list. Let see:
First we have:
List<Function> functions = [f1,f2,f3,f4,f5]
And we want a function like this:
Function resultFunction = (X) -> f5( f4( f3 ( f2( f1(X) ) ) )

How can we easily build a composite function ?

First, we'll use Function::andThen method to wrap each function in another.
Then, we call reduce and the first argument is the starting value, as we are composing functions we use the idempotent element which, in this case, is the Identity Function.

 List<Function> functions = [f1,f2,f3,f4,f5];
 Function compositeFunction = functions.stream().reduce(a -> a, Function::andThen)

What if we want to composite in the reverse order of the list ?
Remember the array is:
List<Function> functions = [f1,f2,f3,f4,f5]
And now we need a function like this:
Function resultFunction = (X) -> f1( f2( f3 ( f4( f5(X) ) ) )

We have to change the accumulator to Function::compose

 List<Function> functions = [f1,f2,f3,f4,f5];
 Function compositeFunction = functions.stream().reduce(a -> a, Function::compose)

Altogether Reduce , Function::compose and Function::andThen conceive a powerfull tool to compose functions which is of great use.

Oldest comments (0)