DEV Community

realNameHidden
realNameHidden

Posted on

3 1 1 1 1

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.

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay