What is the difference between Predicate, Function, Consumer and Supplier in Java?
They are the four core functional interfaces in java.util.function, and they differ in what goes in and what comes out.
Predicate<T> takes one value and returns a boolean. Its method is test. It models a yes-or-no question and is what you pass to filter and removeIf.
Function<T, R> takes one value and returns a value of a different type. Its method is apply. It models a transformation, and it is what you pass to map.
Consumer<T> takes one value and returns nothing. Its method is accept. It models a side effect — logging, printing, writing somewhere — and it is what you pass to forEach.
Supplier<T> takes nothing and returns a value. Its method is get. It models a supplier of values, and it is what you pass to orElseGet or to a lazy initialiser.
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class Main {
public static void main(String[] args) {
Predicate<String> notEmpty = s -> !s.isEmpty();
Function<String, Integer> length = String::length;
Consumer<String> printer = s -> System.out.println("consumed: " + s);
Supplier<String> supplier = () -> "produced on demand";
System.out.println("predicate: " + notEmpty.test("hello"));
System.out.println("function : " + length.apply("hello"));
printer.accept("hello");
System.out.println("supplier : " + supplier.get());
}
}The output shows each one doing its own job: the Predicate answers a question, the Function produces a transformed value, the Consumer performs an action with no result, and the Supplier produces a value from nothing.
There are two more worth knowing. BiFunction, BiConsumer and BiPredicate take two arguments, and the UnaryOperator and BinaryOperator specialisations of Function take an argument of the same type they return, which is what you want for a transform such as doubling.