Built-in Functional Interfaces in Java

Java’s `java.util.function` package provides standard functional interfaces that describe common operations on values. The most important ones for interviews are `Predicate`, `Function`, `Consumer`, `Supplier`, `UnaryOperator`, and `BinaryOperator`.

A functional interface is an interface with exactly one abstract method, making it a target type for a lambda expression or method reference. Java supplies many reusable functional interfaces in `java.util.function`, so you often do not need to declare your own interface for common cases.

`Predicate<T>` represents a test: it accepts a `T` and returns `boolean`. `Function<T, R>` transforms a `T` into an `R`. `Consumer<T>` accepts a value and returns no result, while `Supplier<T>` takes no argument and produces a `T`.

`UnaryOperator<T>` is a specialized `Function<T, T>` where input and output have the same type. `BinaryOperator<T>` is a specialized `BiFunction<T, T, T>` that combines two values of the same type into one value of that type.

These interfaces are commonly used with the Stream API. For example, `filter` commonly receives a `Predicate`, `map` receives a `Function`, and `forEach` receives a `Consumer`. Lambdas provide concise implementations of these interfaces.

Knowing the input and output shape is the fastest way to select the right interface: test a value with `Predicate`, transform it with `Function`, perform an action with `Consumer`, or obtain a value with `Supplier`. For same-type transformations or combinations, use `UnaryOperator` or `BinaryOperator`.

Key points

Interview questions

What is a functional interface in Java?

A functional interface has exactly one abstract method. Because there is one abstract method, a lambda expression can provide its implementation. Functional interfaces can also be used with method references. They may contain additional default and static methods without ceasing to be functional interfaces.

When would you use `Predicate`, `Function`, `Consumer`, and `Supplier`?

Use `Predicate` when you need a boolean test. Use `Function` when you transform one value into another value. Use `Consumer` when you perform an action without returning a result. Use `Supplier` when you need to produce a value without receiving an argument.

What is the difference between `Function` and `UnaryOperator`?

Both represent a one-argument transformation, but `Function<T,R>` allows different input and output types. `UnaryOperator<T>` requires both types to be `T`. Therefore, a unary operator is a specialized form of function for same-type transformations. For example, converting an `Integer` to a `String` needs `Function`, while doubling an `Integer` can use `UnaryOperator<Integer>`.

Why are these interfaces useful with the Stream API?

They let stream operations receive behavior as parameters rather than requiring separate classes for every operation. For example, `filter` uses a predicate to decide which elements remain, while `map` uses a function to transform elements. `forEach` can accept a consumer to perform an action for each element. This makes stream pipelines concise and composable.

How would you decide whether to use a built-in interface or define your own?

First check whether the required behavior matches an existing interface in `java.util.function`. Reusing a standard interface improves familiarity and interoperability with APIs such as Streams. A custom interface can be appropriate when the domain meaning matters or when the method signature communicates intent better than a generic type signature. The choice should balance reuse with readability and domain clarity.