Reducing Operations

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: 10Code 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: abcCode 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: 10Code language: JavaScript (javascript)
For object streams, use mapToInt() with sum():
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
                 .mapToInt(Integer::intValue)
                 .sum();
System.out.println(sum); // Output: 10Code 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: 8Code language: PHP (php)

For primitive streams:

int min = IntStream.of(5, 2, 8, 1)
                   .min()
                   .orElse(0); // Output: 1Code 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 WorldCode 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.

Scroll to Top