Java Programs›Java 8 Streams›Combine Values Using reduce()

Combine Values Using reduce() in Java

intermediate·  Java 8 Streams  ·  Streams

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.

Input
[4, 9, 2, 7, 5]
Output
Sum 27, Product 2520, Max 9

Java Program

Java
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

Sum: 27 Product: 2520 Max: 9

Core Logic

Each reduction needs a combining rule and, usually, an identity value that leaves results unchanged.

How It Works
  1. 1reduce(0, Integer::sum) starts from 0 and adds each element.
  2. 2reduce(1, (a, b) -> a * b) starts from 1, because 0 would make every product 0.
  3. 3reduce(Integer::max) has no identity, so it returns an Optional that's empty for an empty stream.
4 × 9 × 2 × 7 × 5 = 2520.
💡

Key Point: The identity must truly be neutral for the operation — 0 for addition, 1 for multiplication — or parallel reductions give wrong answers.

Complexity
Time Complexity: O(n)Space Complexity: O(1)

Why: Each element is combined once into a single running value.

Key Concepts

reduce(identity, accumulator)reduce(accumulator)Optional

Approach 2: Reducing to a Different Type

Java
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

Longest word: flexible Total letters: 22

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.

How It Works
  1. 1The first reduction keeps whichever word is longer, starting from an empty string.
  2. 2reduce(0, (acc, w) -> acc + w.length(), Integer::sum) sums lengths: the accumulator adds a word, the combiner merges partial sums.
  3. 3The combiner only runs for parallel streams, but it must be supplied.
The four words have 6 + 6 + 2 + 8 = 22 letters, and 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.

Complexity
Time Complexity: O(n)Space Complexity: O(1)

Why: One pass with a single accumulated value.

Key Concepts

three-argument reducecombineraccumulator

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.

Learn the Concept

Related Programs