Java 8 Consumer and Supplier

17 July 2014
By Gonçalo Marques
 
java java8
In this article we will cover Java 8 Consumer and Supplier interfaces.

Introduction

The Consumer and Supplier interfaces are a couple of Functional Interfaces that belong to the new Java 8 java.util.function package. As the package name states, these interfaces are meant to be used together with the new functional Java 8 features.

A complete list of the package interfaces and their descriptions may be found here: java.util.function (Java Platform SE 8).

Supplier

Suppliers represent a function that accepts no arguments and produce a result of some arbitrary type.

Suppliers may reference constructor methods:

Supplier referencing a constructor method

Supplier<User> userSupplier = User::new;
User user = userSupplier.get();

Suppliers may also reference static methods:

Supplier referencing a static method

Supplier<User> userSupplier = UserFactory::produceUser;
User user = userSupplier.get();

class UserFactory {
  public static User produceUser() {
    return new User();
  }
}

Instance methods are also available to be referenced by suppliers:

Supplier referencing an instance method

Supplier<User> userSupplier = this::produceUser;
User user = userSupplier.get();

private User produceUser(){
  return new User();
}

Consumer

Consumers represent a function that accepts a single argument of an arbitrary type and produce no result:

Simple consumer

Consumer<User> userConsumer = (u) -> System.out.println("Username: " 
   + u.getUsername());
userConsumer.accept(user);

Consumers may also be applied to streams of data in order to execute some given action against every stream element:

Consumer applied to a stream

List<User> userList = ...;
userList.stream().forEach((u) -> System.out.println("Username: " + u.getUsername()));

Streams will be covered in a later article.

Asynchronous processing

Even though Java 8 Consumers and Suppliers were included in order to supply functional features, they may remind us of the typical Publisher-Subscriber asynchronous processing architecture.

Java already provides a complete infrastructure in order to implement asynchronous processing, but one could also craft something like the following using Consumers and Suppliers (even if it is just for curiosity):

SupplierConsumer.java

public class SupplierConsumer<T> extends Thread {

  private Supplier<T> supplier;
  private Consumer<T> consumer;
  private boolean shouldRun = true;

  public SupplierConsumer(Supplier<T> supplier, Consumer<T> consumer) {
    this.supplier = supplier;
    this.consumer = consumer;
  }

  @Override
  public void run() {
    while (shouldRun) {
      T item = supplier.get();
      consumer.accept(item);
    }
  }

}

Example usage

BlockingQueue<User> usersQueue = new LinkedBlockingQueue<User>();

Supplier<User> userSupplier = new Supplier<User>() {
  @Override
  public User get() {
    try {
      return usersQueue.take();
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
  }
};

Consumer<User> userConsumer = new Consumer<User>() {
  @Override
  public void accept(User user) {
    System.out.println("Processing user " + user.getUserId());
  }
};

new SupplierConsumer<>(userSupplier, userConsumer).start();

for (int i = 0; i < 100; i++) {
  usersQueue.put(new User(i, "user" + 1));
}

We use a LinkedBlockingQueue as the underlying data structure that holds the items to be processed since it is already synchronized internally.

The Supplier is responsible for taking items from the queue and the Consumer is responsible for process those items.

We left the SupplierConsumer class generic enough so it's just a matter of defining how the Supplier will fetch data that will be later passed to the consumer for processing.

Related Articles

Comments

About the author
Gonçalo Marques is a Software Engineer with several years of experience in software development and architecture definition. During this period his main focus was delivering software solutions in banking, telecommunications and governmental areas. He created the Bytes Lounge website with one ultimate goal: share his knowledge with the software development community. His main area of expertise is Java and open source.

GitHub profile: https://github.com/gonmarques

He is also the author of the WiFi File Browser Android application: