Stream Operations
Stream Reduce
When you need to combine all stream elements into a single result (like summing prices, finding the longest string, or concatenating values), the reduce operation folds elements together using a binary operator.
Reduce with Identity
The reduce operation applies an accumulator function across elements, collapsing the stream into one result. When you provide an identity value, reduce always returns a result (never empty).
import java.util.*;
public class Identity {
public static void main(String[] args) {
List<Integer> nums = ;
int sum = nums.stream().reduce(0, (a, b) -> a + b);
System.out.println("sum = " + sum);
int product = nums.stream().reduce(1, (a, b) -> a * b);
System.out.println("product = " + product);
int max = nums.stream().reduce(Integer.MIN_VALUE, Math::max);
System.out.println("max = " + max);
int emptySum = Collections.<Integer>emptyList().stream().reduce(0, Integer::sum);
System.out.println("emptySum = " + emptySum);
}
}
import java.util.*;
public class Identity {
public static void main(String[] args) {
List<Integer> nums = ;
int sum = nums.stream().reduce(0, (a, b) -> a + b);
System.out.println("sum = " + sum);
int product = nums.stream().reduce(1, (a, b) -> a * b);
System.out.println("product = " + product);
int max = nums.stream().reduce(Integer.MIN_VALUE, Math::max);
System.out.println("max = " + max);
int emptySum = Collections.<Integer>emptyList().stream().reduce(0, Integer::sum);
System.out.println("emptySum = " + emptySum);
}
}
import java.util.*;
public class Identity {
public static void main(String[] args) {
List<Integer> nums = ;
int sum = nums.stream().reduce(0, (a, b) -> a + b);
System.out.println("sum = " + sum);
int product = nums.stream().reduce(1, (a, b) -> a * b);
System.out.println("product = " + product);
int max = nums.stream().reduce(Integer.MIN_VALUE, Math::max);
System.out.println("max = " + max);
int emptySum = Collections.<Integer>emptyList().stream().reduce(0, Integer::sum);
System.out.println("emptySum = " + emptySum);
}
}
Reduce without Identity
Without an identity, reduce returns an Optional since an empty stream has no result.
import java.util.*;
public class OptionalReduce {
public static void main(String[] args) {
List<Integer> nums = ;
Optional<Integer> sum = nums.stream().reduce((a, b) -> a + b);
System.out.println("sum = " + sum.orElse(0));
Optional<Integer> max = nums.stream().reduce((a, b) -> a > b ? a : b);
System.out.println("max = " + max.orElse(-1));
Optional<Integer> emptySum = Collections.<Integer>emptyList().stream().reduce(Integer::sum);
System.out.println("emptySum = " + emptySum.orElse(999));
}
}
import java.util.*;
public class OptionalReduce {
public static void main(String[] args) {
List<Integer> nums = ;
Optional<Integer> sum = nums.stream().reduce((a, b) -> a + b);
System.out.println("sum = " + sum.orElse(0));
Optional<Integer> max = nums.stream().reduce((a, b) -> a > b ? a : b);
System.out.println("max = " + max.orElse(-1));
Optional<Integer> emptySum = Collections.<Integer>emptyList().stream().reduce(Integer::sum);
System.out.println("emptySum = " + emptySum.orElse(999));
}
}
import java.util.*;
public class OptionalReduce {
public static void main(String[] args) {
List<Integer> nums = ;
Optional<Integer> sum = nums.stream().reduce((a, b) -> a + b);
System.out.println("sum = " + sum.orElse(0));
Optional<Integer> max = nums.stream().reduce((a, b) -> a > b ? a : b);
System.out.println("max = " + max.orElse(-1));
Optional<Integer> emptySum = Collections.<Integer>emptyList().stream().reduce(Integer::sum);
System.out.println("emptySum = " + emptySum.orElse(999));
}
}
Custom Reductions
You can reduce to any type by providing an accumulator and combiner for parallel safety.
import java.util.*;
public class Custom {
public static void main(String[] args) {
List<String> words = Arrays.asList("hello", "world", "stream");
String separator = ;
String concat = words.stream().reduce("", (a, b) -> a + b);
System.out.println("concat = '" + concat + "'");
String joined = words.stream().reduce("", (a, b) -> a.isEmpty() ? b : a + separator + b);
System.out.println("joined = '" + joined + "'");
List<Integer> nums = Arrays.asList(10, 20, 30);
int count = nums.stream().reduce(0, (acc, n) -> acc + 1, Integer::sum);
System.out.println("count = " + count);
int totalLength = words.stream().reduce(0, (acc, s) -> acc + s.length(), Integer::sum);
System.out.println("totalLength = " + totalLength);
}
}
import java.util.*;
public class Custom {
public static void main(String[] args) {
List<String> words = Arrays.asList("hello", "world", "stream");
String separator = ;
String concat = words.stream().reduce("", (a, b) -> a + b);
System.out.println("concat = '" + concat + "'");
String joined = words.stream().reduce("", (a, b) -> a.isEmpty() ? b : a + separator + b);
System.out.println("joined = '" + joined + "'");
List<Integer> nums = Arrays.asList(10, 20, 30);
int count = nums.stream().reduce(0, (acc, n) -> acc + 1, Integer::sum);
System.out.println("count = " + count);
int totalLength = words.stream().reduce(0, (acc, s) -> acc + s.length(), Integer::sum);
System.out.println("totalLength = " + totalLength);
}
}
Specialized Reductions
Streams provide shortcuts for common reductions: sum(), min(), max(), count().
import java.util.*;
import java.util.stream.*;
public class Specialized {
public static void main(String[] args) {
List<Integer> nums = ;
int sumViaReduce = nums.stream().reduce(0, Integer::sum);
int sumViaMethod = nums.stream().mapToInt(Integer::intValue).sum();
System.out.println("sumViaReduce = " + sumViaReduce);
System.out.println("sumViaMethod = " + sumViaMethod);
long countViaReduce = nums.stream().reduce(0L, (acc, n) -> acc + 1, Long::sum);
long countViaMethod = nums.stream().count();
System.out.println("countViaReduce = " + countViaReduce);
System.out.println("countViaMethod = " + countViaMethod);
Optional<Integer> maxViaReduce = nums.stream().reduce(Math::max);
Optional<Integer> maxViaMethod = nums.stream().max(Integer::compareTo);
System.out.println("maxViaReduce = " + maxViaReduce.orElse(-1));
System.out.println("maxViaMethod = " + maxViaMethod.orElse(-1));
}
}
import java.util.*;
import java.util.stream.*;
public class Specialized {
public static void main(String[] args) {
List<Integer> nums = ;
int sumViaReduce = nums.stream().reduce(0, Integer::sum);
int sumViaMethod = nums.stream().mapToInt(Integer::intValue).sum();
System.out.println("sumViaReduce = " + sumViaReduce);
System.out.println("sumViaMethod = " + sumViaMethod);
long countViaReduce = nums.stream().reduce(0L, (acc, n) -> acc + 1, Long::sum);
long countViaMethod = nums.stream().count();
System.out.println("countViaReduce = " + countViaReduce);
System.out.println("countViaMethod = " + countViaMethod);
Optional<Integer> maxViaReduce = nums.stream().reduce(Math::max);
Optional<Integer> maxViaMethod = nums.stream().max(Integer::compareTo);
System.out.println("maxViaReduce = " + maxViaReduce.orElse(-1));
System.out.println("maxViaMethod = " + maxViaMethod.orElse(-1));
}
}
import java.util.*;
import java.util.stream.*;
public class Specialized {
public static void main(String[] args) {
List<Integer> nums = ;
int sumViaReduce = nums.stream().reduce(0, Integer::sum);
int sumViaMethod = nums.stream().mapToInt(Integer::intValue).sum();
System.out.println("sumViaReduce = " + sumViaReduce);
System.out.println("sumViaMethod = " + sumViaMethod);
long countViaReduce = nums.stream().reduce(0L, (acc, n) -> acc + 1, Long::sum);
long countViaMethod = nums.stream().count();
System.out.println("countViaReduce = " + countViaReduce);
System.out.println("countViaMethod = " + countViaMethod);
Optional<Integer> maxViaReduce = nums.stream().reduce(Math::max);
Optional<Integer> maxViaMethod = nums.stream().max(Integer::compareTo);
System.out.println("maxViaReduce = " + maxViaReduce.orElse(-1));
System.out.println("maxViaMethod = " + maxViaMethod.orElse(-1));
}
}
Reduce vs Collect
Use reduce for immutable aggregations (sum, max, concatenate). Use collect for mutable reductions (building collections, StringBuilder).
import java.util.*;
public class Pipeline {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
int minLength = ;
int totalLength = words.stream()
.filter(s -> s.length() >= minLength)
.map(String::length)
.reduce(0, Integer::sum);
System.out.println("totalLength = " + totalLength);
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
int evenProduct = nums.stream()
.filter(n -> n % 2 == 0)
.reduce(1, (a, b) -> a * b);
System.out.println("evenProduct = " + evenProduct);
Optional<String> longest = words.stream()
.reduce((a, b) -> a.length() > b.length() ? a : b);
System.out.println("longest = " + longest.orElse(""));
}
}
import java.util.*;
public class Pipeline {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
int minLength = ;
int totalLength = words.stream()
.filter(s -> s.length() >= minLength)
.map(String::length)
.reduce(0, Integer::sum);
System.out.println("totalLength = " + totalLength);
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
int evenProduct = nums.stream()
.filter(n -> n % 2 == 0)
.reduce(1, (a, b) -> a * b);
System.out.println("evenProduct = " + evenProduct);
Optional<String> longest = words.stream()
.reduce((a, b) -> a.length() > b.length() ? a : b);
System.out.println("longest = " + longest.orElse(""));
}
}
import java.util.*;
public class Pipeline {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
int minLength = ;
int totalLength = words.stream()
.filter(s -> s.length() >= minLength)
.map(String::length)
.reduce(0, Integer::sum);
System.out.println("totalLength = " + totalLength);
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
int evenProduct = nums.stream()
.filter(n -> n % 2 == 0)
.reduce(1, (a, b) -> a * b);
System.out.println("evenProduct = " + evenProduct);
Optional<String> longest = words.stream()
.reduce((a, b) -> a.length() > b.length() ? a : b);
System.out.println("longest = " + longest.orElse(""));
}
}
Exercise: Practical.java
Reduce a list of orders to calculate total revenue and find the largest order