Course Content
Stream API
Stream API
Consumer: Processing Data
You've already explored many functional interfaces in Java, but what if you need to perform an operation that takes an argument, applies some changes, or produces a side effect—without returning a result? This is where the Consumer
functional interface comes in.
Consumer Interface
It is commonly used for performing actions that modify state or produce side effects without returning a value.
The Consumer
interface is part of the java.util.function package
and is defined as follows:
The accept(T t)
method takes an object of type T
as input and performs an operation on it without returning a result.
Practical Application
Let's say you have a list of strings, and for each string, you need to print it along with a unique id, separated by a space. You can achieve this using the Consumer
interface by passing each string along with its index (id
).
Main
package com.example; import java.util.List; import java.util.function.Consumer; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); // Creating a `Consumer` that prints each string with its id Consumer<String> printNameWithId = (name) -> { int id = names.indexOf(name) + 1; // id = index + 1 System.out.println(id + " " + name); }; // Using `Consumer` to print each string with its id names.forEach(printNameWithId); } }
In this example, you use Consumer
to print each string from the list with a unique identifier. The id for each element is calculated using its index in the list, and the result is printed in the format "id string"
. This allows us to process list elements without explicitly using a loop.
You can also simplify our code by writing the lambda expression directly inside the forEach
loop:
Main
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); // Using `forEach` with a lambda expression to print the ID and name names.forEach(name -> System.out.println((names.indexOf(name) + 1) + " " + name)); } }
As you can see, the result remains the same, with the code becoming more concise and easier to read.
Using Default Method
The Consumer
interface also includes a default method that enables combining multiple operations.
The andThen()
method allows you to chain two Consumer
operations together. The first Consumer
runs first, followed by the second one.
For example, imagine you have a list of names, and you want to perform two tasks: printing each name in uppercase and then printing the length of that name. By using andThen()
, you can combine both operations into a single Consumer
that applies them sequentially.
Main
package com.example; import java.util.List; import java.util.function.Consumer; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); // First `Consumer` — prints the name in uppercase Consumer<String> printUpperCase = name -> System.out.print(name.toUpperCase() + " - "); // Second `Consumer` — prints the length of the name Consumer<String> printLength = name -> System.out.println(name.length()); // Combine both `Consumers` using `andThen()` Consumer<String> combinedConsumer = printUpperCase.andThen(printLength); // Apply the combined `Consumer` to each name names.forEach(combinedConsumer); } }
In this example, you first print the name in uppercase, followed by a dash and the name's length. You use andThen()
to combine two Consumer
operations so that the first prints the name, and the second prints its length.
1. What does the andThen()
method in the Consumer
interface do?
2. What type of data does the accept method in the Consumer
interface take?
Thanks for your feedback!