What are the core functional interfaces in java.util.function (Function, Predicate, Supplier, Consumer)?

8 minbeginnerfunctional-interfacesfunctionpredicatesupplierconsumer

Quick Answer

Function<T,R> takes a T and returns an R (a transformation). Predicate<T> takes a T and returns boolean (a test/filter condition). Supplier<T> takes nothing and returns a T (a lazy value source/factory). Consumer<T> takes a T and returns nothing (an action performed on a value). Together they cover most shapes of behavior passed as arguments throughout the Stream API and modern JDK methods.

Detailed Answer

java.util.function defines a small set of general-purpose functional interfaces covering the most common "shapes" of behavior, so you rarely need to declare your own:

InterfaceMethodSignature shapeTypical use
Function<T, R>R apply(T t)takes one, returns a (possibly different) typetransforming a value
Predicate<T>boolean test(T t)takes one, returns booleanfiltering / conditions
Supplier<T>T get()takes nothing, returns a valuelazy value creation / factories
Consumer<T>void accept(T t)takes one, returns nothingperforming an action on a value
BiFunction<T,U,R>R apply(T t, U u)two inputs, one outputcombining two values
UnaryOperator<T>T apply(T t)Function<T,T> specializationtransform within the same type
BinaryOperator<T>T apply(T a, T b)BiFunction<T,T,T> specializationreduction/combining, same type
Function<String, Integer> length = String::length;
Predicate<String> isLong = s -> s.length() > 5;
Supplier<List<String>> newList = ArrayList::new;
Consumer<String> printer = System.out::println;

list.stream()
    .filter(isLong)              // Predicate
    .map(length)                 // Function
    .forEach(printer::accept);   // Consumer

Optional.ofNullable(cachedValue)
    .orElseGet(newList);         // Supplier — lazily creates only if needed

Most also have default combinator methods for composing behavior without writing a new lambda from scratch — e.g., Predicate.and()/or()/negate(), Function.andThen()/compose(). There are also primitive-specialized variants (IntPredicate, ToIntFunction<T>, IntSupplier, ...) to avoid autoboxing overhead in numeric-heavy code.