Java Reference
In-Depth Information
Let's consider the following snippet of code that performs the reduce operation in the imperative programming
style. The code computes the sum of all integers in a list.
// Create the list of integers
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Declare an accumulator called sum and initialize (or seed) it to zero
int sum = 0;
// Accumulate the partial results in sum
for(int num : numbers) {
// Accumulate the partial result in sum
sum = sum + num;
}
// Print the result
System.out.println(sum);
15
The code declares a variable named
sum
and initializes the variable to 0. If there is no element in the list, the
initial value of
sum
becomes the result. The for-each loop traverses the list and keeps storing the partial results in
the
sum
variable, using it as an accumulator. When the for-each loop finishes, the
sum
variable contains the result. As
pointed out in the beginning of this chapter, such a for-loop has no room for parallelization; the entire logic must be
executed in a single thread.
Consider another example that computes the sum of incomes of
persons
in a list:
// Declare an accumulator called sum and initialize it to zero
double sum = 0.0;
for(Person person : Person.persons()) {
// Map the Person to his income double
double income = person.getIncome();
// Accumulate the partial result in sum
sum = sum + income;
}
System.out.println(sum);
This time, you had to perform an additional step to map the
Person
to his income before you could accumulate
the partial results in the
sum
variable.
The
Stream<T>
interface contains a
reduce()
method to perform the reduce operation. The method has three
overloaded versions:
T reduce(T identity, BinaryOperator<T> accumulator)
•
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
•
Optional<T> reduce(BinaryOperator<T> accumulator)
•