Reduction Operations
Combining a stream into one value — reduce() forms, identity/accumulator/combiner, sum, count, max, min, average and parallel reduction.
#Introduction
If map() transforms data and filter() selects data, then reduce() combines all elements into a single result.
This topic is a favourite in 5–10 years Java interviews because it tests both Stream knowledge and problem-solving. By the end of this chapter you'll master reduce(); identity, accumulator and combiner; sum(), count(), max(), min(), average(); Optional; custom reductions; and parallel reduction.
#What is Reduction?
Reduction means combining multiple elements into a single result.
The stream becomes one value.
#reduce() Syntax
// Version 1
Optional<T> reduce(BinaryOperator<T> accumulator)
// Version 2
T reduce(T identity, BinaryOperator<T> accumulator)
// Version 3 (mainly for parallel streams / type-changing reductions)
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner)#Sum Using reduce()
List<Integer> numbers = Arrays.asList(2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println(sum);14Equivalent lambda: .reduce(0, (a, b) -> a + b).
How It Works Internally
#More reduce() Examples
Product of Numbers
int product = numbers.stream()
.reduce(1, (a, b) -> a * b);
System.out.println(product);120Why is the identity 1? Because 1 × x = x. If the identity were 0, every result would become 0.
Find Maximum and Minimum
Optional<Integer> max = numbers.stream().reduce(Integer::max);
System.out.println(max.get()); // 5
Optional<Integer> min = numbers.stream().reduce(Integer::min);
System.out.println(min.get()); // 2Longest String
List<String> names = Arrays.asList("John", "Alexander", "Bob", "David");
String longest = names.stream()
.reduce("", (a, b) -> a.length() > b.length() ? a : b);
System.out.println(longest);AlexanderConcatenate Strings
String result = names.stream()
.reduce("", (a, b) -> a + b);
System.out.println(result);JohnAlexanderBobDavid#Why Optional?
List<Integer> list = Collections.emptyList();
list.stream().reduce(Integer::sum);What should Java return? Instead of null, Java returns Optional.empty(). Safe code:
numbers.stream()
.reduce(Integer::sum)
.ifPresent(System.out::println);
int total = numbers.stream()
.reduce(Integer::sum)
.orElse(0);#Specialized Reduction Methods
sum()
Instead of numbers.stream().reduce(0, Integer::sum), use:
numbers.stream()
.mapToInt(Integer::intValue)
.sum();Cleaner and faster.
count(), max(), min(), average()
long count = numbers.stream().count(); // 4
Optional<Integer> max = numbers.stream().max(Integer::compareTo);
Optional<Integer> min = numbers.stream().min(Integer::compareTo);
double avg = numbers.stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0); // 3.5Employee Examples
// Total salary
double totalSalary = employees.stream()
.mapToDouble(Employee::getSalary)
.sum();
// Average salary
double avg = employees.stream()
.mapToDouble(Employee::getSalary)
.average()
.orElse(0);
// Highest-paid employee
Employee highest = employees.stream()
.max(Comparator.comparing(Employee::getSalary))
.orElseThrow();
// Lowest-paid employee
Employee lowest = employees.stream()
.min(Comparator.comparing(Employee::getSalary))
.orElseThrow();#reduce() vs collect()
| reduce() | collect() |
|---|---|
| Combines elements into one value | Collects elements into a container |
| List → one result | List → another List / Set / Map |
| Sum, product, maximum, longest string | List, Set, Map |
#Parallel Reduction
Suppose 1, 2, 3, 4.
This is why associative operations like addition and multiplication work well with parallel streams.
#Real Spring Boot Examples
// Total order amount
double total = orders.stream()
.mapToDouble(Order::getAmount)
.sum();
// Count active users
long count = users.stream()
.filter(User::isActive)
.count();
// Most expensive product
Product expensive = products.stream()
.max(Comparator.comparing(Product::getPrice))
.orElseThrow();
// Longest username
String longest = users.stream()
.map(User::getName)
.reduce("", (a, b) -> a.length() > b.length() ? a : b);#Interview Questions
Q1What is the identity value in reduce()?
It is the starting value of the reduction — 0 for sum, 1 for product, "" for string concatenation.
Q2Why use Optional?
Because the stream may be empty.
Q3Difference between sum() and reduce()?
| sum() | reduce() |
|---|---|
| Built for numeric sums | General-purpose reduction |
| Simpler | More flexible |
| Faster for numeric primitives | Works for any reduction |
Q4When should you use reduce()?
When you need to combine all elements into a single result that isn't directly provided by specialized methods like sum() or count().
Q5Can every sum() be written with reduce()?
Yes — e.g. numbers.stream().reduce(0, Integer::sum).
#Practice Problems
List<Integer> numbers = Arrays.asList(2, 5, 8, 10, 15);- Find the sum.
- Find the product.
- Find the maximum.
- Find the minimum.
- Find the average.
- Count the elements.
- Find the sum of even numbers.
- Find the product of odd numbers.
- Find the second highest number (using previous lessons).
- Find the total of squares.
class Employee {
int id;
String name;
String department;
double salary;
}- Total salary.
- Average salary.
- Highest salary.
- Lowest salary.
- Employee with the highest salary.
- Employee with the lowest salary.
- Count employees.
- Sum salaries of the HR department.
- Average salary of the IT department.
- Longest employee name.
Interview Challenge (5+ Years)
Filter employees with salary > 50,000, increase each salary by 10%, and find the total increased salary:
double total = employees.stream()
.filter(e -> e.getSalary() > 50_000)
.mapToDouble(e -> e.getSalary() * 1.10)
.sum();Each operation has a clear responsibility: filter() keeps relevant employees, mapToDouble() transforms salaries, sum() reduces to a single value.
#Senior Java Tips
- Prefer specialized methods (
sum(),count(),average(),max(),min()) overreduce()when available — they're clearer and optimized. - Choose the correct identity in
reduce(). An incorrect identity (like0for multiplication) leads to incorrect results. - Keep reduction operations associative if you plan to use
parallelStream(). Addition and multiplication are safe; order-dependent operations may produce unexpected results.
#Chapter Summary
- What reduction is
- The three forms of
reduce() - Identity, accumulator and combiner
sum(),count(),max(),min(),average()- Why reductions return
Optional reduce()vscollect()- Parallel reduction and associativity