Card 04/ 09

ComparisonDifficulty: Intermediate1 min

Function vs Predicate vs Consumer vs Supplier

Four interfaces cover almost every lambda, separated by whether it takes something and whether it gives something back.

The package java.util.function ships general-purpose functional interfaces so you rarely write your own. Four cover almost everything, and two questions separate them: does it take a value, and does it give one back?

The four core functional interfaces, by what they take and give
InterfaceTakesGives backThe methodWritten as
Function<T, R>A TAn Rapplys -> s.length()
Predicate<T>A TA booleantests -> s.isBlank()
Consumer<T>A TNothingaccepts -> System.out.println(s)
Supplier<T>NothingA Tget() -> new ArrayList<>()

The decision rule. Work out what goes in and what comes out and the interface is decided. A Predicate is only a Function that returns a boolean, and it exists separately because filtering is common enough to deserve a name and and, or and negate to combine with.

Two variants turn up constantly. BiFunction<T, U, R> takes two arguments, and UnaryOperator<T> is a Function whose input and output are the same type, which is what List.replaceAll wants.

So when a method signature takes one of these, it is telling you the shape of the lambda, the inline function, to write: a Predicate<Invoice> wants invoice -> something true or false, and a Supplier<List<Invoice>> wants () -> a new list.