Reducing operations in Java Streams are used to combine elements of a stream into a single result using an associative accumulation function. These operations are also known as fold operations because they repeatedly apply a binary operator to the elements, progressively reducing them to a single value.
1. reduce() Method
The reduce() method performs a reduction on stream elements using an associative accumulation function, producing a single result. It comes in three forms:
a. reduce(BinaryOperator<T>)
Reduces the stream to an Optional<T> using a BinaryOperator. No initial value is provided, so it returns Optional.empty() for empty streams.
import java.util.*; import java.util.stream.*; public class Main { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4); Optional<Integer> sum = numbers.stream() .reduce((a, b) -> a + b); System.out.println(sum.orElse(0)); // Output: 10 } }
b. reduce(T identity, BinaryOperator<T>)
Reduces the stream starting with an identity (initial value) and applies a BinaryOperator. Returns a value of type T (not Optional).
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println(sum); // Output: 10
Code language: PHP (php)
- Identity: The initial value (e.g., 0 for addition, 1 for multiplication).
- Returns the identity for empty streams.
- Commonly used for operations like sum or product.
c. reduce(U identity, BiFunction<U, T, U> accumulator, BinaryOperator<U> combiner)
A more general form for reducing to a different type or with parallel streams. It takes an identity, an accumulator, and a combiner.
List<String> words = Arrays.asList("a", "b", "c");
String concatenated = words.stream()
.reduce("", (acc, word) -> acc + word, (s1, s2) -> s1 + s2);
System.out.println(concatenated); // Output: abc
Code language: JavaScript (javascript)
- Accumulator: Combines the accumulated result (U) with a stream element (T).
- Combiner: Merges partial results in parallel streams.
- Useful for complex reductions or parallel processing.
2. Specialized Reducing Operations
For common reductions, Java 8 provides specialized methods that are more readable and efficient than reduce().
a. Summing (sum() for primitive streams)
For primitive streams (IntStream, LongStream, DoubleStream), use sum().
int sum = IntStream.of(1, 2, 3, 4)
.sum();
System.out.println(sum); // Output: 10
Code language: JavaScript (javascript)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
.mapToInt(Integer::intValue)
.sum();
System.out.println(sum); // Output: 10
Code language: PHP (php)
b. Min and Max (min(), max())
Find the minimum or maximum element using a Comparator or natural ordering.
List<Integer> numbers = Arrays.asList(5, 2, 8, 1);
Optional<Integer> min = numbers.stream()
.min(Comparator.naturalOrder());
System.out.println(min.orElse(null)); // Output: 1
Optional<Integer> max = numbers.stream()
.max(Comparator.naturalOrder());
System.out.println(max.orElse(null)); // Output: 8
Code language: PHP (php)
For primitive streams:
int min = IntStream.of(5, 2, 8, 1)
.min()
.orElse(0); // Output: 1
Code language: JavaScript (javascript)
c. Counting (count())
Counts the number of elements in the stream.
a. Collecting to a List or Set
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
List<Integer> list = numbers.stream()
.collect(Collectors.toList());
System.out.println(list); // Output: [1, 2, 3, 4]
Set<Integer> set = numbers.stream()
.collect(Collectors.toSet());
System.out.println(set); // Output: [1, 2, 3, 4] (order not guaranteed)
Code language: PHP (php)
b. Joining Strings
List<String> words = Arrays.asList("Hello", "World");
String joined = words.stream()
.collect(Collectors.joining(" "));
System.out.println(joined); // Output: Hello World
Code language: JavaScript (javascript)
c. Grouping and Partitioning
Group elements by a key or partition based on a predicate.
List<Person> people = Arrays.asList(
new Person("Anand", 25),
new Person("Bharat", 20),
new Person("Charan", 25)
);
// Group by age
Map<Integer, List<Person>> byAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge));
System.out.println(byAge); // Output: {20=[Bharat(20)], 25=[Anand(25), Charan(25)]}
// Partition by age > 21
Map<Boolean, List<Person>> partitioned = people.stream()
.collect(Collectors.partitioningBy(p -> p.getAge() > 21));
System.out.println(partitioned); // Output: {false=[Bharat(20)], true=[Anand(25), Charan(25)]}
//Person class for reference
class Person {
String name;
int age;
Person(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }
@Override
public String toString() { return name + "(" + age + ")"; }
}
Code language: JavaScript (javascript)
d. Summarizing Statistics
For numerical data, use summarizingInt(), summarizingLong(), or summarizingDouble() to compute multiple statistics (sum, count, min, max, average).
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
IntSummaryStatistics stats = numbers.stream()
.collect(Collectors.summarizingInt(Integer::intValue));
System.out.println(stats); // Output: IntSummaryStatistics{count=4, sum=10, min=1, average=2.5, max=4}
Code language: PHP (php)
Common Use Cases
- Aggregation: Sum, product, or concatenation (e.g., summing salaries, joining strings).
- Collection building: Create lists, sets, or maps from stream elements.
- Statistics: Compute min, max, average, or count for numerical data.
- Grouping: Organize data by categories (e.g., group employees by department).
Reducing operations in Java Streams are fundamental for summarizing, aggregating, and processing stream elements into a single result, making them powerful tools for data reduction and analysis tasks in Java programming.