Java Stream Reduce: A Practical Guide
Java Streams' reduce operation transforms a sequence of elements into a single result through repeated application of an accumulator function, embodying the essence of functional reduction patterns.
Core Method Overloads
Three primary signatures handle different scenarios. The basic Optional<T> reduce(BinaryOperator<T> accumulator) pairwise combines elements, returning Optional for empty stream safety.
The identity form T reduce(T identity, BinaryOperator<T> accumulator) supplies a starting value like 0 for sums, guaranteeing results even from empty streams.
Advanced reduce(T identity, BiFunction<T,? super U,R> accumulator, BinaryOperator<R> combiner) supports parallel execution and type conversion from stream <T> to result <R>.
Reduction folds elements left-to-right: begin with identity (or first element), accumulate each subsequent item. For [1,2,3] summing, compute ((0+1)+2)+3.
Parallel streams divide work into subgroups, requiring an associative combiner to merge partial results reliably.
Basic Reductions
Sum integers: int total = IntStream.range(1, 11).reduce(0, Integer::sum); // 55.
Maximum value: OptionalInt max = IntStream.range(1, 11).reduce(Math::max); //OptionalInt[10].
String concatenation: String joined = Stream.of("Hello", " ", "World").reduce("", String::concat); //Hello World.
Object comparison:
record Car(String model, int price) {
}
var cars = List.of(
new Car("Model A", 20000),
new Car("Model B", 30000),
new Car("Model C", 25000)
);
Optional<Car> priciest = cars.stream().reduce((c1,c2) -> c1.price > c2.price ? c1 : c2); //Optional[Car[model=Model B, price=30000]]
Advanced: Different Types
Three-argument overload converts stream <T> to result <R>:
// IntStream → formatted String
String squares = IntStream.of(1,2,3)
.boxed()
.reduce("",
(accStr, num) -> accStr + (num * num) + ", ",
String::concat); // "1, 4, 9, "
Employee list → summary:
record Employee(String name, String dept) {
}
var employees = List.of(
new Employee("John", "IT"),
new Employee("Tom", "Sales")
);
String summary = employees.stream()
.reduce("",
(acc, emp) -> acc + emp.name() + "-" + emp.dept() + " | ",
String::concat); // "John-IT | Tom-Sales | "
Parallel execution demands the combiner to merge thread-local String partials.
| Sequential Execution | Parallel (with combiner) |
|---|---|
((0+1)+2)+3 |
(0+1) + (2+3) → 1+5 |
""+"1"+"4" |
""+"1" + ""+"4" → "1"+"4" |
Performance Tips
Use parallelStream() with proper combiner: list.parallelStream().reduce(0, (a,b)->a+b, Integer::sum).
Opt for primitive streams (IntStream, LongStream) to eliminate boxing overhead.
Prefer sum(), max(), collect(joining()) for simple cases; reserve custom reduce for complex logic or type transformations.
Recent Comments