135

As a non-Java programmer learning Java, I am reading about Supplier and Consumer interfaces at the moment. And I can't wrap my head around their usage and meaning.

When and why you would use these interfaces? Can someone give me a simple layperson example of this?

I'm finding the Doc examples not succinct enough for my understanding.

james emanon
  • 11,185
  • 11
  • 56
  • 97
  • 7
    Each Page of the API Doc has a link labelled “USE” at the top which you can click for [`Consumer`](http://docs.oracle.com/javase/8/docs/api/java/util/function/class-use/Consumer.html) and [`Supplier`](http://docs.oracle.com/javase/8/docs/api/java/util/function/class-use/Supplier.html) You may also search the [tutorial](http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) for `Consumer`… – Holger Feb 09 '15 at 20:53
  • 14
    I love the answer by Stuart Marks. And I think most people who answered below missed the point. The question is not "how" to write Suppliers, Consumers and Functions. It is "why" in the world would you want to? For a person who is not used to them, they make the code much more complex. But the benefit of using them is not clear. – anton1980 Feb 16 '19 at 01:09
  • As far as I can see (and I share your frustration with the tangential descriptions) it's just a slick way of abstracting both object-type and object-treatment from an object used in a piece of code. This allows application of this same code to many different types of object by simply defining different new classes and injecting them into the Supplier and Consumer interfaces. So, in a police record system, the same superficial code is used for all suspects but the final printout for each depends on each suspect's classification, e.g. 'citizen', 'petty', 'larcen', 'felon', 'hardened', etc. – Trunk Jul 07 '19 at 12:49

7 Answers7

210

The reason you're having difficulty grasping the meaning of functional interfaces such as those in java.util.function is that the interfaces defined here do not have any meaning! They are present primarily to represent structure, not semantics.

This is atypical for most Java APIs. The typical Java API, such as a class or interface, has meaning, and you can develop a mental model for what it represents and use that to understand the operations on it. Consider java.util.List for example. A List is a container of other objects. They have a sequence and an index. The number of objects contained in the list is returned by size(). Each object has an index in the range 0..size-1 (inclusive). The object at index i can be retrieved by calling list.get(i). And so forth.

The functional interfaces in java.util.function don't have any such meaning. Instead, they're interfaces that merely represent the structure of a function, such as the number of arguments, the number of return values, and (sometimes) whether an argument or return value is a primitive. Thus we have something like Function<T,R> which represents a function that takes a single argument of type T and returns a value of type R. That's it. What does that function do? Well, it can do anything ... as long as it takes a single argument and returns a single value. That's why the specification for Function<T,R> is little more than "Represents a function that accepts one argument and produces a result."

Clearly, when we're writing code, it has meaning, and that meaning has to come from somewhere. In the case of the functional interfaces, the meaning comes from the context in which they're used. The interface Function<T,R> has no meaning in isolation. However, in the java.util.Map<K,V> API, there is the following:

V computeIfAbsent(K key, Function<K,V> mappingFunction)

(wildcards elided for brevity)

Ah, this use of Function is as a "mapping function". What does that do? In this context, if key is not already present in the map, the mapping function is called and is handed the key and is expected to produce a value, and the resulting key-value pair is inserted into the map.

So you can't look at the specification for Function (or any of the other functional interfaces, for that matter) and attempt to discern what they mean. You have to look at where they're used in other APIs to understand what they mean, and that meaning applies only to that context.

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
  • 7
    So basically, it's just function as type – Jack Guo Jan 13 '19 at 14:45
  • May be another useful information is that functional interfaces can have multiple implemented methods that can add behavior to your code – Jhon Mario Lotero Jan 16 '20 at 15:03
  • 1
    the last two paragraphs resolved the mystery (or at least what remained of it) for me. I first encountered Suppliers as I was trying to write (or learn to write) a Minecraft mod using forge's API. The walk-through I'm following showed writing a function that received a Supplier for the argument named "block", and based on what you're saying, this is probably because blocks can provide different things depending on its drop table (though usually it drops itself). Is that the general idea here? A class that, depending on context, may "get" (or set, in the case of consumers) different things? – Twisted on STRIKE at1687989253 Jun 16 '21 at 14:48
116

This is Supplier:

public Integer getInteger() {
    return new Random().nextInt();
}

This is Consumer:

public void sum(Integer a, Integer b) {
    System.out.println(a + b);
}

So in layman terms, a supplier is a method that returns some value (as in its return value). Whereas, a consumer is a method that consumes some value (as in method argument), and does some operations on them.

Those will transform to something like these:

// new operator itself is a supplier, of the reference to the newly created object
Supplier<List<String>> listSupplier = ArrayList::new;
Consumer<String> printConsumer = a1 -> System.out.println(a1);
BiConsumer<Integer, Integer> sumConsumer = (a1, a2) -> System.out.println(a1 + a2);

As for usage, the very basic example would be: Stream#forEach(Consumer) method. It takes a Consumer, which consumes the element from the stream you're iterating upon, and performs some action on each of them. Probably print them.

Consumer<String> stringConsumer = (s) -> System.out.println(s.length());
Arrays.asList("ab", "abc", "a", "abcd").stream().forEach(stringConsumer);
Simeon Leyzerzon
  • 18,658
  • 9
  • 54
  • 82
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • 3
    So, a Supplier is a way to create an instance of a method that returns 'something'? – james emanon Feb 09 '15 at 19:55
  • 3
    @jamesemanon Exactly. That might be a method reference, or a lambda. – Rohit Jain Feb 09 '15 at 19:56
  • 21
    What is the benefit of this rather than calling the method directly? Is it because the Supplier can act like an intermediary and hand off that "return" value? – james emanon Feb 09 '15 at 20:21
  • 2
    Consumer is not valid. A consumer has a single type parameter. – johnlemon May 06 '16 at 07:32
  • 6
    But WHY create such a construct ? What problem is solved by having it in Java ? – Trunk Jul 08 '19 at 13:54
  • 1
    @Trunk I can speak specifically about the Supplier interface which solved a real world problem. The main advantage in the case was deferred execution. During object A creation another object B that it depends may not be available. So instead of passing objectB to the constructor of objectA you pass a supplier of objectB. When ObjectA actually calls supplier.get() it is able to get the latest value of ObjectB which has potentially now the latest correct value. Especially useful when Object A itself is implementing a method of interface that you can't change. – Plaiska Oct 08 '20 at 23:10
  • @Plaiska Interesting application. The Consumer acts like a marketmaker in a stock market transaction where there is someone willing to sell for X but no end-user of the stock is offering to buy at X. The marketmaker brokerage steps in to buy at X in the belief that eventually a buyer will bid at some price Y > X . . . My own idea was that Supplier and Consumer prevent the creation of *unnecessary new objects of class T*. Supplier allows us to reuse an existing object instead, if one is available and idle. Consumer allows us do some void operation(s) with a T object's data. – Trunk Oct 09 '20 at 17:09
  • public void sum(Integer a, Integer b) { System.out.println(a + b); } Is incorrect for Consumer. – Arafath Apr 03 '22 at 17:20
38

A Supplier is any method which takes no arguments and returns a value. Its job is literally to supply an instance of an expected class. For instance, every reference to a 'getter' method is a Supplier

public Integer getCount(){
    return this.count;
}

Its instance method reference myClass::getCount is an instance of Supplier<Integer>.

A Consumer is any method which takes arguments and returns nothing. It is invoked for its side-effects. In Java terms, a Consumer is an idiom for a void method. 'setter' methods are a good example:

public void setCount(int count){
    this.count = count;
}

Its instance method reference myClass::setCount is an instance of Consumer<Integer> and IntConsumer.

A Function<A,B> is any method which takes an argument of one type, and returns another. This can be referred to as a 'transformation'. The Function<A,B> takes an A and returns a B. Notable is that for a given value of A, the function should always return a specific value of B. A and B can in fact be the same type, such as the following:

public Integer addTwo(int i){
    return i+2;
}

Its instance method reference myClass:addTwo is a Function<Integer, Integer> and a ToIntFunction<Integer>.

A Class method reference to a getter is another example of a function.

public Integer getCount(){
    return this.count;
}

Its class method reference MyClass::getCount is an instance of Function<MyClass,Integer> and ToIntFunction<MyClass>.

Steve K
  • 4,863
  • 2
  • 32
  • 41
21

Why are Consumer/Supplier/other functional interfaces defined in java.util.function package: Consumer and Supplier are two, among many, of the in-built functional interfaces provided in Java 8. The purpose of all these in-built functional interfaces is to provide a ready "template" for functional interfaces having common function descriptors(functional method signatures/definitions).

Lets say we have a required to convert a type T to another type R. If we were to pass any function defined like this as a parameter to a method, then that method would need to define a Functional Interface whose functional/abstract method takes parameter of type T as input and gives a parameter of type R as output. Now, there could be many scenarios like this and the programmer(s) would end up defining multiple functional interfaces for their needs. To avoid this kind of a scenario, ease programming & bring a common standard in usage of functional interfaces, a set of in-built functional interfaces such as Predicate, Function, Consumer & Supplier have been defined.

What does Consumer do: Consumer functional interface accepts an input, does something with that input and does not give any output. Its definition is like this (from Java Source) -

@FunctionalInterface
public interface Consumer<T> {
 void accept(T t);
}

Here accept() is the functional\abstract method which does takes an input and returns no output. So, if you want to input an Integer, do something with it with no output then instead of defining your own interface use an instance of Consumer.

What does Supplier do: Supplier functional interface does not take any input but returns an output. Its defined like this(from Java Source) -

@FunctionalInterface
public interface Supplier<T> {
  T get();
}

Wherever you need a function which returns something, say an Integer, but takes no output use an instance of Supplier.

In case more clarity, along with example usage, of Consumer & Supplier interfaces is needed then you can refer my blog posts on the same - http://www.javabrahman.com/java-8/java-8-java-util-function-consumer-tutorial-with-examples/ and http://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/

Stephane
  • 11,836
  • 25
  • 112
  • 175
Dhruv Rai Puri
  • 1,335
  • 11
  • 20
12

1. Meaning

See my answers to my question here and also another here, but in short these new Interfaces provide convention and descriptiveness for everyone to use (+ funky method chaining such as .forEach(someMethod().andThen(otherMethod()))

2. Differences

Consumer: Takes something, does something, returns nothing: void accept(T t)

Supplier: Takes nothing, returns something : T get() (reverse of Consumer, basically a universal 'getter' method)

3. Usage

// Consumer: It takes something (a String) and does something (prints it) 
    List<Person> personList = getPersons();

     personList.stream()
                    .map(Person::getName)    
                    .forEach(System.out::println); 

Supplier: wrap repetitive code, e.g. code execution timing

public class SupplierExample {

    public static void main(String[] args) {

        // Imagine a class Calculate with some methods
        Double result1 = timeMe(Calculate::doHeavyComputation);
        Double result2 = timeMe(Calculate::doMoreComputation);
    }
    private static Double timeMe(Supplier<Double> code) {

        Instant start = Instant.now();
        // Supplier method .get() just invokes whatever it is passed
        Double result = code.get();
        Instant end = Instant.now();

        Duration elapsed = Duration.between(start,end);
        System.out.println("Computation took:" + elapsed.toMillis());

        return result;
    }
}
Community
  • 1
  • 1
Andrejs
  • 10,803
  • 4
  • 43
  • 48
1

Consumer and supplier are the interfaces provided by java. Consumer is use for iterate over the list elements and supplier is use for supply object's

you can easily understand with code demonstration.

Consumer

package com.java.java8;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * The Class ConsumerDemo.
 *
 * @author Ankit Sood Apr 20, 2017
 */
public class ConsumerDemo {

    /**
     * The main method.
     *
     * @param args
     *            the arguments
     */
    public static void main(String[] args) {

    List<String> str = new ArrayList<>();
    str.add("DEMO");
    str.add("DEMO2");
    str.add("DEMO3");

    /* Consumer is use for iterate over the List */
    Consumer<String> consumer = new Consumer<String>() {
        @Override
        public void accept(String t) {

        /* Print list element on consile */
        System.out.println(t);
        }
    };

    str.forEach(consumer);

    }

}

Supplier

package com.java.java8;

import java.util.function.Supplier;

/**
 * The Class SupplierDemo.
 *
 * @author Ankit Sood Apr 20, 2017
 */
public class SupplierDemo {

    /**
     * The main method.
     *
     * @param args
     *            the arguments
     */
    public static void main(String[] args) {
    getValue(() -> "Output1");
    getValue(() -> "OutPut2");
    }

    /**
     * Gets the value.
     *
     * @param supplier
     *            the supplier
     * @return the value
     */
    public static void getValue(Supplier<?> supplier) {
    System.out.println(supplier.get());
    }

}
Ankit Sood
  • 257
  • 3
  • 5
0

In Laymen terms,

supplier will supply data but without consuming any data. In programming terms a method which doesn't take any argument but return a value. It is used to generate new values.

http://codedestine.com/java-8-supplier-interface/

consumer will consume data and but do not return any data. In programming terms a method which takes multiple argument and does not return any value.

http://codedestine.com/java-8-consumer-interface/

lalitbhagtani
  • 459
  • 5
  • 6