**Java 8 reduce** is a great method to compute a value from stream of values – reduce collection to value. In this post we’ll explain how reduce in **Java** work.

## reduce(T initial, BinaryOperator accumulator)

This version takes **initial value**, goes through all the values in a stream, and passes each of them, with result of previous computation, to the **accumulator** function to compute the result (maybe sounds complex, but it’s simple):

List<Integer> numbers = asList(1, 2, 3, 4, 5); int sum = numbers.stream().reduce(0, (a, b) -> { System.out.printf("summing(%s, %s)%n", a, b); return Integer.sum(a, b); }); System.out.println("Sum: " + sum);

In the output you can see that on the left is **already accumulated value** (initially 0) and on the right is **subsequent value from the stream**:

summing(0, 1) summing(1, 2) summing(3, 3) summing(6, 4) summing(10, 5) Sum: 15

## reduce(BinaryOperator accumulator) to Optional

This version returns **Optional**, because it **doesn’t have initial value**, and when the stream would be empty the reduction wouldn’t be able to return any value. Compare these two examples:

List<Integer> numbers = asList(1, 2, 3, 4, 5); Optional<Integer> result = numbers.stream() .reduce(Integer::sum); int sum = result.orElse(0); System.out.println("Sum: " + sum);

The above code produces the following output:

Sum: 15

If the collection would be empty the value from **orElse(0)** would be used as in this example:

// empty list == empty stream! List<Integer> numbers = emptyList(); Optional<Integer> result = numbers.stream() .reduce(Integer::sum); int sum = result.orElse(0); System.out.println("Sum: " + sum);

The code gives:

Sum: 0

## reduce(T initial, BiFunction accumulator, BinaryOperator combiner)

This, three parameter, **reduction** is designed to be used with **parallelStream**, else it will behave as normal **reduce** with initial value and accumulator function. First, let’s create a simple **combiner** that will log values being combined:

static BinaryOperator<Integer> COMBINER = (a, b) -> { System.out.printf("combining(%s, %s)%n", a, b); return Integer.sum(a, b); };

In the first example we’re going to use the **combiner** version, but on simple, non-parallel **stream**:

List<Integer> numbers = asList(1, 2, 3, 4, 5); int sum = numbers.stream() // init, accumulator, combiner .reduce(0, Integer::sum, COMBINER); System.out.println("Sum: " + sum);

As you can see, the program prints only the accumulated value, because the **combiner** haven’t been called:

Sum: 15

Only when we use the **parallelStream** the **combiner** comes into action:

List<Integer> numbers = asList(1, 2, 3, 4, 5); int sum = numbers.parallelStream() // init, accumulator, combiner .reduce(0, Integer::sum, COMBINER); System.out.println("Sum: " + sum);

Now the intermediate values, accumulated by **accumulator function**, are passed to the **combiner** for final accumulation:

combining(4, 5) combining(3, 9) combining(1, 2) combining(3, 12) Sum: 15