DEV Community

realNameHidden
realNameHidden

Posted on

How does reduce() differ from collect() in Java streams?

The reduce() and collect() methods in Java Streams serve different purposes and operate at different levels of abstraction. Here’s a detailed comparison:

1. reduce()

The reduce() method is used for reducing a stream of elements to a single result using a reduction operation (e.g., summing, concatenating, finding min/max).

Key Characteristics:

Works with immutable reductions.

Operates on a stream to produce a single result (e.g., Integer, Double, String).

Typically used with associative, non-interfering, and stateless operations.

Examples of reduce() Usage:

Summing Numbers:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
int sum = numbers.stream()
                 .reduce(0, Integer::sum); // 0 is the identity value
System.out.println(sum); // Output: 15

Enter fullscreen mode Exit fullscreen mode

Concatenating Strings:

List<String> words = List.of("Hello", "World");
String result = words.stream()
                     .reduce("", (s1, s2) -> s1 + " " + s2);
System.out.println(result.trim()); // Output: Hello World

Enter fullscreen mode Exit fullscreen mode

Finding Maximum:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
int max = numbers.stream()
                 .reduce(Integer.MIN_VALUE, Integer::max);
System.out.println(max); // Output: 5

Enter fullscreen mode Exit fullscreen mode

Limitations of reduce():

Produces a single value.
Less flexible when compared to collect(), especially for mutable reductions.

2. collect()

The collect() method is used to accumulate elements into a mutable container (e.g., List, Set, Map) or perform more complex reductions. It is typically used with Collectors utility methods.

Key Characteristics:

Designed for mutable reductions.

Produces a collection or other complex result, such as List, Set, Map, or a custom structure.

Works in conjunction with the Collectors class.

Examples of collect() Usage:
Collecting into a List:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> result = numbers.stream()
                              .collect(Collectors.toList());
System.out.println(result); // Output: [1, 2, 3, 4, 5]

Enter fullscreen mode Exit fullscreen mode

Collecting into a Set:

List<Integer> numbers = List.of(1, 2, 2, 3, 4, 4);
Set<Integer> result = numbers.stream()
                             .collect(Collectors.toSet());
System.out.println(result); // Output: [1, 2, 3, 4]

Enter fullscreen mode Exit fullscreen mode

Grouping Elements:

List<String> names = List.of("Alice", "Bob", "Anna", "Charlie");
Map<Character, List<String>> groupedByFirstLetter = names.stream()
    .collect(Collectors.groupingBy(name -> name.charAt(0)));
System.out.println(groupedByFirstLetter);
// Output: {A=[Alice, Anna], B=[Bob], C=[Charlie]}

Enter fullscreen mode Exit fullscreen mode

Advantages of collect() over reduce():

Works with mutable containers like collections.

Supports parallel processing by combining partial results efficiently.

Offers a variety of pre-built collectors via Collectors.

When to Use Which?

Use reduce() When:

You need a single result from the stream (e.g., sum, product, max, min).

The reduction logic is simple and associative.

Use collect() When:

You need to transform the stream into a collection (e.g., List, Set, Map).

You need to group, partition, or perform complex accumulations.

You want to use pre-built Collectors for common tasks.

Example Comparison
Task: Sum the squares of numbers in a list.

Using reduce():

List<Integer> numbers = List.of(1, 2, 3, 4);
int sumOfSquares = numbers.stream()
                          .map(n -> n * n)
                          .reduce(0, Integer::sum);
System.out.println(sumOfSquares); // Output: 30

Enter fullscreen mode Exit fullscreen mode

Using collect() (less ideal for this task but possible):

List<Integer> numbers = List.of(1, 2, 3, 4);
int sumOfSquares = numbers.stream()
                          .map(n -> n * n)
                          .collect(Collectors.summingInt(Integer::intValue));
System.out.println(sumOfSquares); // Output: 30

Enter fullscreen mode Exit fullscreen mode

In general, prefer reduce() for straightforward, immutable reductions and collect() for anything involving collections or more complex operations.

Top comments (0)