JB Header
Java 8 java.util.function.Consumer Tutorial with Examples
Tutorial explains the in-built functional interface Consumer<T> introduced in Java 8. It uses examples to show how the accept() & andThen() methods of the Consumer interface are to be used. What is java.util.function.Consumer Consumer<T> is an in-built functional interface introduced in Java 8 in the java.util.function package. Consumer can be used in all contexts where an object needs to be consumed,i.e. taken as input, and some operation is to be performed on the object without returning any result. Common example of such an operation is printing where an object is taken as input to the printing function and the value of the object is printed( we will expand upon the printing example in more detail below when understanding how to use Consumer interface).

Since Consumer is a functional interface, hence it can be used as the assignment target for a lambda expression or a method reference.
In case you are new to functional programming then you might want to go through functional interfaces and lambda expressions tutorials before proceeding ahead - functional interfaces tutorialClick to Read tutorial on Functional Interfaces , lambda expressions tutorialClick to read Lambda Expressions tutorial . Function Descriptor of Consumer<T> Consumer's Function Descriptor is T -> (). This means an object of type T is input to the lambda with no return value. To understand Function Descriptors in details you can refer the function descriptor tutorial Tutorial explaining function descriptors.
Advantage of predefined java.util.function.Consumer In all scenarios where an object is to be taken as input and an operation performed on it, the in-built functional interface Consumer<T> can be used without the need to define a new functional interface every time.
java.util.function.Consumer source code
@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); };
    }
}
Salient Points regarding Consumer<T>’s source code
  • Consumer has been defined with the generic type T which is the same type which its accept() & andThen() methods take as input.
  • accept() method is the primary abstract method of the Consumer functional interface. Its function descriptor being T -> (). I.e. accept() method takes as input the type T and returns no value. I will explain usage of accept() with detailed example in the next section.
  • All lambda definitions for Consumer must be written in accordance with accept method's signature, and conversely all lambdas with the same signature as that of accept() are candidates for assignment to an instance of Consumer interface.
  • andThen() is a default method Click to Read Detailed Tutorial on Default Methods in Java 8 in Consumer interface. Method andThen(), when applied on a Consumer interface, takes as input another instance of Consumer interface and returns as a result a new consumer interface which represents aggregation of both of the operations defined in the two Consumer interfaces. I will explain the usage of andThen() with a detailed example in coming sections.
Usage of accept() method of Consumer To understand the accept() method lets take a look at the example below where I take a list of integers and print them using a method printList(). The printList() method takes 2 inputs- an instance of Consumer interface which contains the printing logic and the list which is to be printed. Lets have a look at the code now, post which I will explain in detail how this code works -
Code showing usage of Consumer.accept() method
package com.javabrahman.java8;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class ConsumerFunctionExample{
  public static void main(String args[]){
    Consumer<Integer> consumer= i-> System.out.print(" "+i);
    List<Integer> integerList=Arrays.asList(new Integer(1), 
                              new Integer(10), new Integer(200),
                              new Integer(101), new Integer(-10),
                              new Integer(0));
    printList(integerList, consumer);
 }
 public static void printList(List<Integer> listOfIntegers, Consumer<Integer> consumer){
  for(Integer integer:listOfIntegers){
    consumer.accept(integer);
  }
 }
}

 OUTPUT on executing the above code
  1  10  200  101  -10  0
Explanation of above example's Code & Output
  • ConsumerFunctionExample is my class with 2 methods - main() & printList().
  • In main() method first an instance of Consumer<Integer> is defined(named consumer) using a lambda expressionLink to Lambda Expressions Tutorial which takes input as an object of type Integer and contains logic to print the value of that Integer.
  • Next the main() method defines a new list of integers and passes it to the printList() method along with the consumer object defined earlier which contains the printing logic.
  • The printList() method iterates through the list of integers and invokes the accept() method of the consumer object for every integer in the list.
  • The accept() method which works as per the lambda definition assigned to the consumer interface, i.e. i-> System.out.print(" "+i) , prints out the value of each integer with a single space character prepended to it. Thus giving the output 1 10 200 101 -10 0 .
Usage of default method andThen() of Consumer To understand the andThen() default method of Consumer interface, I have taken the same code as that used for example of accept() method above and changed it a bit to show andThen() works.
Code showing usage of default method Consumer.andThen()
//import statements are same as in previous example; hence skipped
public class ConsumerFunctionExample{
 public static void main(String args[]){
  Consumer<Integer> consumer= i-> System.out.print(" "+i);
  Consumer<Integer> consumerWithAndThen = consumer.andThen( i-> System.out.print("(printed "+i+")"));
  List<Integer> integerList=Arrays.asList(new Integer(1),
                            new Integer(10), new Integer(200),
                            new Integer(101), new Integer(-10),
                            new Integer(0));
  printList(integerList,consumerWithAndThen);
 }
 public static void printList(List<Integer> listOfIntegers, Consumer<Integer> consumer){
  for(Integer integer:listOfIntegers){
   consumer.accept(integer);
  }
 }
}
 Output on executing the above code
  1(printed  1)  10(printed  10)  200(printed  200)  101(printed  101)  -10(printed  -10)  0(printed  0)
Explanation of the code
  • A new instance of Consumer interface is defined which is assigned a value of the previous consumer interface(which prints just the space pepended integer) aggregated with the new lambda (which prints (printed i) where i is replaced by the value of the integer passed as input to the lambda).
  • We thus have two Consumer Interface based operations aggregated - first one prints the integer value and the second one prints (print i) where i is the value of the integer passed.
  • The consumer interface instance representing aggregated consumer operations is passed as parameter to the printList() method.
  • The printList() method is still the same as previous example i.e. it simply calls the accept() method on the consumer interface passed to it while iterating through the list of integers passed to it.
  • While in the previous example the consumer interface passed to it contained a single operation which simply printed the integer value prepended with a single space character; this time the consumer interface does two operations which have been aggregated together for each value - printing the integer value with space prepended and then printing the string (printed i) where is is the integer passed to it. The output of this example is thus -
    1(printed  1)  10(printed  10)  200(printed  200)  101(printed  101)  -10(printed  -10)  0(printed  0)
Summary In this tutorial we looked at what is the Consumer<T> in-built interface defined in Java 8 and what are its advantages. We then looked at how to use the Consumer interface using its accept() method & the andThen() default method.