Java 8's java.util.function package ships a set of general-purpose functional interfaces covering the most common shapes of behavior, so developers rarely need to define their own for everyday tasks.
Key Points: • Function<T,R> takes one argument and returns a result, via its apply() method — used heavily in map(). • Consumer<T> takes one argument and returns nothing, via accept() — used in forEach(). • Supplier<T> takes no arguments and returns a value, via get() — used for lazy value creation. • Predicate<T> takes one argument and returns a boolean, via test() — used in filter(). • BiFunction<T,U,R>, BinaryOperator<T>, and UnaryOperator<T> extend these ideas to two-argument or same-type cases, and primitive variants like IntFunction avoid autoboxing.
Example: Function<String, Integer> toLength = String::length; captures the idea of turning a String into an Integer, and can be passed directly to Stream.map() on a stream of strings.
Code Example:
Function<String, Integer> toLength = String::length;
Consumer<String> printer = System.out::println;
Supplier<String> greeting = () -> "Hello";
Predicate<String> isEmpty = String::isEmpty;
System.out.println(toLength.apply("Java")); // 4Interview Tip: A concise interview answer is:
"The core ones are Function for a one-argument transformation, Consumer for a one-argument action with no return value, Supplier for producing a value with no input, and Predicate for a one-argument boolean test. There are also two-argument variants like BiFunction, and primitive versions like IntFunction to avoid boxing — together they cover almost every shape of lambda you'd write."