Combine Values Using reduce() in Java
Problem
Reducing repeatedly combines a running result with the next element until a single value is left, such as a total or a maximum.
Given a list of integers, compute their sum, product and maximum using reduce.
Java Program
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class ReduceStreamExample {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(4, 9, 2, 7, 5);
int sum = nums.stream().reduce(0, Integer::sum); // identity 0, combine with +
int product = nums.stream().reduce(1, (a, b) -> a * b); // identity 1, combine with *
Optional<Integer> max = nums.stream().reduce(Integer::max); // no identity -> Optional
System.out.println("Sum: " + sum);
System.out.println("Product: " + product);
System.out.println("Max: " + max.get());
}
}Output
Core Logic
Each reduction needs a combining rule and, usually, an identity value that leaves results unchanged.
- 1
reduce(0, Integer::sum)starts from 0 and adds each element. - 2
reduce(1, (a, b) -> a * b)starts from 1, because 0 would make every product 0. - 3
reduce(Integer::max)has no identity, so it returns anOptionalthat's empty for an empty stream.
Key Point: The identity must truly be neutral for the operation — 0 for addition, 1 for multiplication — or parallel reductions give wrong answers.
Why: Each element is combined once into a single running value.
Key Concepts
Approach 2: Reducing to a Different Type
import java.util.Arrays;
import java.util.List;
public class ReduceToString {
public static void main(String[] args) {
List<String> words = Arrays.asList("stream", "reduce", "is", "flexible");
String longest = words.stream()
.reduce("", (best, w) -> w.length() > best.length() ? w : best);
int totalLength = words.stream()
.reduce(0, (acc, w) -> acc + w.length(), Integer::sum); // accumulator + combiner
System.out.println("Longest word: " + longest);
System.out.println("Total letters: " + totalLength);
}
}
Output
Core Logic
Reductions can carry any result type: the two-argument form keeps the same type, and the three-argument form can turn strings into a number.
- 1The first reduction keeps whichever word is longer, starting from an empty string.
- 2
reduce(0, (acc, w) -> acc + w.length(), Integer::sum)sums lengths: the accumulator adds a word, the combiner merges partial sums. - 3The combiner only runs for parallel streams, but it must be supplied.
flexible is the longest.Key Point: For type-changing reductions, mapToInt(String::length).sum() is usually clearer — reach for three-argument reduce only when no simpler form exists.
Why: One pass with a single accumulated value.
Key Concepts
Interview Questions
What's the difference between reduce and collect?
reduce combines immutable values into a new value at each step. collect mutates a container such as a list or map, which is more efficient for building collections.
Why does reduce without an identity return Optional?
Because the stream might be empty, and then there's no first element to start from.