Java 8 Reduction
Introduction
Reduction assumes an important role in functional programming. It is usually executed as the last step of a sequence of functional operations that are executed over a stream of elements and produces a final result. This result may be a single result (ex: sum, average, or any other arbitrary operation) or a collection of results (ex: word count in a document, grouped by word).
In this article we will see how to perform reductions in Java. Keep in mind that we will only cover reductions that produce a single result. Reductions that produce results in the format of collections will be covered in the next article.
Java Reduction
We start by defining a collection that will serve as the data source for the following reductions:
List<Integer> integerList = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
Now let's perform a reduction that will sum all the even numbers that are present in the original collection:
int result = integerList .stream() .filter((i) -> i % 2 == 0) .reduce(0, (i1, i2) -> i1 + i2); // Will print 20 System.out.println(result);
Here the reduce operation accepts two arguments: the first is the identity, that represents the base case, or the initial value. The base case will be the default value if the stream is empty. Since we are adding up integer values we define the base case as zero.
The second argument is the accumulator which also takes two arguments: the first is the current partial result of the reduction. The second argument is the current item of the stream that is actually being processed. The accumulator must return a result that represents a new partial result.
In our example, the accumulator adds the current partial result to the current stream item. Since the initial partial result - or the base case - is zero, the final result will be the sum of the filtered stream items: 20.
We may also omit the first argument of the reduce operation:
Optional<Integer> result = integerList .stream() .filter((i) -> i % 2 == 0) .reduce((i1, i2) -> i1 + i2); // Will print 20 System.out.println(result.isPresent() ? result.get() : null);
If the initial value argument is omitted from the reduce operation, the first stream element to be processed will be used as the initial value. Since the stream may be empty, the return type of this kind of reduction must be of type Optional (if the stream is empty and no initial value is specified, the reduction will return an Optional without any wrapped value).
More info about the Optional type in Java 8 Optional.