Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Aggregating Elements with the reduce() Method | Terminal Operations in the Stream API
Stream API
course content

Course Content

Stream API

Stream API

1. Fundamentals and Functional Capabilities of Stream API
4. Practical Applications of Stream API

book
Aggregating Elements with the reduce() Method

When working with collections in Java, you often need to reduce all elements to a single result, such as a sum, product, or another aggregated value.

There are three variations of the reduce() method, each designed for different scenarios. Let's go through each one in detail.

reduce() with a Single Parameter

If you need to aggregate elements without an initial value, you can use this version of reduce(). However, since the stream might be empty, the method returns an Optional<T>.

This method applies the accumulator function to all elements in the stream and returns an Optional<T>.

Practical Example

Imagine an online store with a list of products and their prices. The goal is to calculate the total revenue of all products in the store.

java

Main

copy
1234567891011121314151617181920212223242526272829303132333435363738
package com.example; import java.util.List; import java.util.Optional; public class Main { public static void main(String[] args) { List<Product> products = List.of( new Product("Laptop", 1200.0), new Product("Mouse", 25.0), new Product("Keyboard", 75.0) ); Optional<Double> totalRevenue = products.stream() .map(Product::getPrice) .reduce(Double::sum); totalRevenue.ifPresent(revenue -> System.out.println("Total revenue: " + revenue)); } } class Product { private String name; private double price; public Product(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public double getPrice() { return price; } }

This code creates a list of products, then uses reduce() to sum up the prices. The map(Product::getPrice) method extracts the price of each product, while Double::sum performs the summation. If the result is present, it is printed.

reduce() with Two Parameters

If you want to ensure a guaranteed return value, even when the stream is empty, use the reduce() method with an identity parameter. The initial value ensures a stable computation.

This version of reduce() starts with the given identity value, ensuring that a result is always returned, even for an empty stream.

Practical Example

Suppose a store has a cash register with an initial balance, and you need to add the total price of all products to determine the potential total cash available.

java

Main

copy
12345678910111213141516171819202122232425262728293031323334353637
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<Product> products = List.of( new Product("Laptop", 1200.0), new Product("Mouse", 25.0), new Product("Keyboard", 75.0) ); double totalRevenue = products.stream() .map(Product::getPrice) .reduce(500.0, Double::sum); System.out.println("Total revenue with initial balance: " + totalRevenue); } } class Product { private String name; private double price; public Product(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public double getPrice() { return price; } }

Here, the code extracts prices with map(Product::getPrice) and applies reduce(500.0, Double::sum), where 500.0 represents the initial balance, and Double::sum adds up the values.

reduce() for Parallel Processing

This version of reduce() is designed for cases where more complex transformations are required, and results need to be aggregated in parallel.

This method takes three parameters:

  • identity – the initial value;
  • accumulator – a function that transforms each element;
  • combiner – a function that merges partial results.

Practical Example

In an online store, you need to calculate the total number of characters in all product names. This can be useful for setting limits on receipt length.

java

Main

copy
123456789101112131415161718192021222324252627282930313233343536
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<Product> products = List.of( new Product("Laptop", 1200.0), new Product("Mouse", 25.0), new Product("Keyboard", 75.0) ); int totalLength = products.stream() .reduce(0, (sum, product) -> sum + product.getName().length(), Integer::sum); System.out.println("Total name length: " + totalLength); } } class Product { private String name; private double price; public Product(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public double getPrice() { return price; } }

The code iterates through the list of products using reduce(), where 0 is the initial value, (sum, product) -> sum + product.getName().length() defines the logic for summing the lengths of product names, and Integer::sum combines the results in a parallel processing environment.

1. What data type does reduce(BinaryOperator<T> accumulator) return if the stream might be empty?

2. When should you use reduce(T identity, BinaryOperator<T> accumulator)?

question mark

What data type does reduce(BinaryOperator<T> accumulator) return if the stream might be empty?

Select the correct answer

question mark

When should you use reduce(T identity, BinaryOperator<T> accumulator)?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

Section 3. Chapter 6
We're sorry to hear that something went wrong. What happened?
some-alt