Functional Interfaces Review — Consumer
In this series, I am planning to brush up on different ways we can leverage Functional Interfaces like Consumer, BiConsumer, Predicate, BiPredicate, Supplier and Function.
As we already know, functional interface in Java is an interface with just one abstract method, and it can have any number of default or static methods. The Consumer interface is a well-known functional interface in Java, defined in the java.util.functionpackage. It represents an operation that takes a single input argument and returns no result. Here is everything you need to know about the Consumer interface, along with examples:
Get Full Stack Developer’s stories in your inbox
Join Medium for free to get updates from this writer.
The Interface as defined in Java —
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}Methods
- accept(T t): This is the single abstract method of the
Consumerinterface. It takes one argument and performs the operation on it. - andThen(Consumer<? super T> after): This is a default method that returns a composed
Consumerthat performs, in sequence, this operation followed by theafteroperation.
Key Points
- Since
Consumeris a functional interface, it can be implemented using lambda expressions or method references. Consumeris often used for operations that operate via side effects.
Usage Examples
Basic Example
Here’s a simple example of how to use the Consumer interface:
import java.util.function.Consumer;
public class ConsumerExample {
public static void main(String[] args) {
// Define a Consumer that prints the input string
Consumer<String> printConsumer = s -> System.out.println(s);
// Use the Consumer
printConsumer.accept("Hello, World!");
}
}Chaining Consumers
You can chain multiple Consumer instances using the andThen method:
import java.util.function.Consumer;
public class ConsumerChainingExample {
public static void main(String[] args) {
// Define two Consumers
Consumer<String> firstConsumer = s -> System.out.println("First consumer: " + s);
Consumer<String> secondConsumer = s -> System.out.println("Second consumer: " + s.toUpperCase());
// Chain the Consumers
Consumer<String> combinedConsumer = firstConsumer.andThen(secondConsumer);
// Use the combined Consumer
combinedConsumer.accept("Hello, World!");
}
}Using Method References
You can also use method references with Consumer:
import java.util.function.Consumer;
import java.util.List;
public class MethodReferenceExample {
public static void main(String[] args) {
// Define a Consumer using a method reference
Consumer<String> printConsumer = System.out::println;
// Use the Consumer with a List
List<String> names = List.of("Alice", "Bob", "Charlie");
names.forEach(printConsumer);
}
}Using Consumer with Collections
The forEach method of collections accepts a Consumer:
import java.util.List;
import java.util.function.Consumer;
public class ListConsumerExample {
public static void main(String[] args) {
List<String> list = List.of("one", "two", "three");
// Define a Consumer that prints each item
Consumer<String> printConsumer = System.out::println;
// Use the Consumer with the list
list.forEach(printConsumer);
}
}Practical Use Cases
- Logging:
Consumercan be used to log items in a list. - UI Development: Processing UI events.
- Stream API: Used extensively with the Stream API to perform operations on each element of a stream.
- Side-effects in Streams: Performing side-effects in streams such as modifying state or writing to a file.
Summary
The Consumer interface is a powerful tool in Java that allows for operations that act on a single input without returning any result. Its primary purpose is to encapsulate side-effect operations, and it is especially useful in functional programming paradigms, such as with the Stream API and lambda expressions.






