Consumer is an interface added in java 8.
It is a Functional interface with a single abstract method accept()
which takes an argument and returns no value, that is, its return type is void
.
Thus, this method consumes a value and hence the name of the interface.
Consumer
behaves just opposite to java 8 Supplier interface which takes no argument and returns a value.
Signature of accept()
method is
void accept(T t);
where T is the generic type.
Creating Consumer
Since Consumer
is a Functional interface, it can be represented as a Lambda expression which matches the signature of accept()
method as shown below.
Consumer<String> consumer = (str) -> System.out.println(str);
Here, the expression to the right is a Lambda expression which takes a single argument and returns nothing.
There is another primitive way of creating a Consumer as well. Since Consumer is an interface, you can not create its object directly but as an anonymous inner class as shown below.
Consumer<String> c = new Consumer<>() { @Override public void accept(String arg) { System.out.println(arg); } };
Clearly, the primitive approach is much lengthier as compared to Lambda expression.
Invoking a Consumer
Once a Consumer is created, you can invoke it by calling its accept method as shown below.
// create a consumer Consumer<String> printer = (str) -> System.err.println(str); // invoke it printer.accept("Hello World!")'
Why use Consumer
You might ask why should I use Consumer
just to print something, I can directly do that. But, there are scenarios where using Consumer is beneficial and required.
They are:
1. Many methods in java api expect an object of type Consumer such as forEach
method in java.lang.Iterable
interface.
forEach
is a default interface method added in java 8.
2. A Consumer
may be used to modify an object supplied to it such as squaring an integer supplied to it.
Both these will be covered in the examples below.
Consumer interface Example
Below program iterates over a list and prints its elements using a Consumer.
// create a consumer Consumer<String> printer = (str) -> System.err.println(str); // initialize a list List<String> list = List.of("Learning", "Consumer", "at", "codippa.com"); // iterate the list list.forEach(printer);
This example iterates over a list using forEach method and passes a Consumer to it. forEach will invoke the Consumer for each list element and print it to the console.
Here is the output
Learning
Consumer
at
codippa.com
As stated above, a
Consumer
may be used to modify the element supplied to it.Below program creates a
Consumer
of Integer object and adds 10 to its value.
//create a consumer Consumer<Integer> adder = (num) -> { num += 10; System.out.println(num); }; // invoke consumer adder.accept(50); // prints 60
Chaining Consumers
Chaining consumers means combining multiple consumers to produce a required result.
Consumer interface contains a method andThen()
which expects a Consumer
argument and returns a Consumer
. This is a default interface method and can be used to chain consumers.
Below example creates multiple consumers, where one consumer iterates over a list, capitalizes its elements and another consumer then prints its elements.
All this is done using single consumer invocation as shown below.
// initialize a list List<String> list = new ArrayList<>(); // add elements list.add("Learning"); list.add("Consumer"); list.add("at"); list.add("codippa.com"); // create a consumer to iterate list and print Consumer<List<String>> printer = (items) -> items. forEach(item -> System.out.println(item)); // create a consumer to capitalize its elements Consumer<List<String>> capitalizer = (items) -> { for (int i = 0; i < items.size(); i++) { items.set(i, items.get(i).toUpperCase()); } }; // chain consumers capitalizer.andThen(printer).accept(list);
Notice how multiple consumers are invoked in a single statement. Input to all the consumers is supplied using accept()
method at the end.
Output of this example is
LEARNING
CONSUMER
AT
CODIPPA.COM
Note that in this example, we are not using List.of()
method to create a list but using add()
method for adding elements to the list.
If you don’t do this, then you will get an UnsupportedOperationException while modifying list elements as below
Exception in thread “main” java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:73)
If you look at the source of andThen()
method, it is
default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; }
which shows that it invokes the accept()
method of this Consumer
and then the accept()
method of Consumer
supplied as argument.