Java Built-in Functional Interfaces Interview Questions and Answers | Predicate, Function, Consumer, Supplier | Java 8

Master Java Built-in Functional Interfaces with real interview questions, Predicate, Function, Consumer, Supplier, BiFunction, UnaryOperator, BinaryOperator, Spring Boot examples, and production best practices.


Built-in Functional Interfaces Interview Questions and Answers

Introduction

Java 8 introduced several built-in Functional Interfaces in the java.util.function package to support Functional Programming and Lambda Expressions.

Before Java 8, developers often created custom interfaces for simple operations.

Example:

public interface EmployeeValidator {
    boolean validate(Employee employee);
}

Java 8 eliminated the need for many custom interfaces by providing reusable Functional Interfaces such as:

  • Predicate
  • Function
  • Consumer
  • Supplier
  • UnaryOperator
  • BinaryOperator
  • BiPredicate
  • BiFunction
  • BiConsumer

These interfaces are heavily used in:

  • Spring Boot
  • Stream API
  • Spring Data JPA
  • Kafka
  • CompletableFuture
  • Reactive Programming
  • Collection APIs

Understanding them is essential for senior Java interviews.


Learning Objectives

After completing this article, you'll understand:

  • Why built-in Functional Interfaces were introduced
  • Predicate
  • Function
  • Consumer
  • Supplier
  • UnaryOperator
  • BinaryOperator
  • BiPredicate
  • BiFunction
  • BiConsumer
  • Primitive Functional Interfaces
  • Function chaining
  • Production examples
  • Interview questions

Functional Interface Hierarchy

flowchart TD

FunctionalInterfaces --> Predicate

FunctionalInterfaces --> Function

FunctionalInterfaces --> Consumer

FunctionalInterfaces --> Supplier

Function --> UnaryOperator

Function --> BinaryOperator

Predicate --> BiPredicate

Function --> BiFunction

Consumer --> BiConsumer

Most Common Functional Interfaces

Interface Input Output Purpose
Predicate 1 boolean Validation
Function<T,R> 1 Result Transformation
Consumer 1 Nothing Process data
Supplier None Result Generate data
UnaryOperator 1 Same Type Modify object
BinaryOperator 2 Same Type Combine objects

Predicate

Represents a condition.

Method

boolean test(T t)

Example

Predicate<Employee> highSalary =
emp -> emp.getSalary() > 100000;

Usage

employees.stream()
         .filter(highSalary)
         .toList();

Function

Transforms one object into another.

Method

R apply(T value)

Example

Function<Employee,String> mapper =
Employee::getName;

Usage

employees.stream()
         .map(mapper)
         .toList();

Consumer

Consumes data without returning a value.

Method

void accept(T value)

Example

Consumer<Employee> printer =
System.out::println;

Usage

employees.forEach(printer);

Supplier

Produces data without taking input.

Method

T get()

Example

Supplier<UUID> generator =
UUID::randomUUID;

Usage

UUID id = generator.get();

UnaryOperator

A specialization of Function<T,T> where input and output types are the same.

UnaryOperator<String> upper =
String::toUpperCase;

BinaryOperator

A specialization of BiFunction<T,T,T> where both inputs and output are the same type.

BinaryOperator<Integer> max =
Integer::max;

Execution Flow

flowchart LR

Input --> FunctionalInterface["Functional Interface"]

FunctionalInterface["Functional Interface"] --> Lambda

Lambda --> BusinessLogic["Business Logic"]

BusinessLogic["Business Logic"] --> Result

Production Example

Predicate<Employee> active =
Employee::isActive;

Function<Employee,String> mapper =
Employee::getName;

Consumer<String> printer =
System.out::println;

employees.stream()
         .filter(active)
         .map(mapper)
         .forEach(printer);

Spring Boot Example

List<EmployeeDTO> dtos =
repository.findAll()
          .stream()
          .filter(Employee::isActive)
          .map(EmployeeDTO::new)
          .toList();

This combines multiple built-in Functional Interfaces in a single Stream pipeline.


Frequently Asked Interview Questions


Question 1

What are built-in Functional Interfaces?

Answer

They are predefined Functional Interfaces available in the java.util.function package.

They eliminate the need to create custom interfaces for common operations such as validation, transformation, consumption, and object creation.


Question 2

Why did Java introduce built-in Functional Interfaces?

Answer

Before Java 8, developers repeatedly created custom interfaces for simple tasks.

Built-in Functional Interfaces:

  • Reduce boilerplate code
  • Improve code reuse
  • Standardize APIs
  • Integrate seamlessly with Lambda Expressions and Streams

Question 3

What is Predicate?

Answer

Predicate<T> represents a condition that returns a boolean.

Method:

boolean test(T value)

Example:

Predicate<Integer> even =
number -> number % 2 == 0;

Common use cases:

  • Filtering
  • Validation
  • Authorization
  • Business rules

Question 4

What is Function?

Answer

Function<T,R> transforms one object into another.

Method:

R apply(T value)

Example:

Function<Employee,String> mapper =
Employee::getName;

Common use cases:

  • DTO conversion
  • Entity mapping
  • Data transformation

Question 5

What is Consumer?

Answer

Consumer<T> accepts input but returns no result.

Method:

void accept(T value)

Example:

Consumer<String> logger =
System.out::println;

Common use cases:

  • Logging
  • Sending notifications
  • Writing files
  • Processing records

Question 6

What is Supplier?

Answer

Supplier<T> produces an object without accepting input.

Method:

T get()

Example:

Supplier<LocalDateTime> now =
LocalDateTime::now;

Common use cases:

  • Lazy initialization
  • Random value generation
  • UUID creation
  • Default object creation

Question 7

What is the difference between Consumer and Supplier?

Answer

Consumer Supplier
Takes input Takes no input
Returns nothing Returns an object
accept() get()

Example:

Consumer<String> printer =
System.out::println;

Supplier<String> message =
() -> "Hello";

Question 8

What is UnaryOperator?

Answer

UnaryOperator<T> extends Function<T,T>.

Input and output types are the same.

Example:

UnaryOperator<String> upper =
String::toUpperCase;

Used when modifying an object without changing its type.


Question 9

What is BinaryOperator?

Answer

BinaryOperator<T> extends BiFunction<T,T,T>.

It accepts two values of the same type and returns one value of the same type.

Example:

BinaryOperator<Integer> max =
Integer::max;

Question 10

What is BiPredicate?

Answer

BiPredicate<T,U> accepts two parameters and returns a boolean.

Example:

BiPredicate<String,String> equals =
String::equals;

Common use cases:

  • Comparing values
  • Validation involving two inputs

Question 11

What is BiFunction?

Answer

BiFunction<T,U,R> accepts two parameters and returns a result.

Example:

BiFunction<String,String,String> join =
(a,b) -> a + b;

Question 12

What is BiConsumer?

Answer

BiConsumer<T,U> accepts two parameters and returns nothing.

Example:

BiConsumer<String,Integer> printer =
(name,age) ->
System.out.println(name + ":" + age);

Question 13

What are Primitive Functional Interfaces?

Answer

Primitive Functional Interfaces avoid boxing and unboxing overhead.

Examples:

  • IntPredicate
  • LongPredicate
  • DoublePredicate
  • IntConsumer
  • LongSupplier
  • DoubleFunction

Using primitive variants improves performance when processing large amounts of primitive data.


Question 14

Can Functional Interfaces be chained?

Answer

Yes.

Examples:

Function chaining:

Function<String,String> trim =
String::trim;

Function<String,String> upper =
String::toUpperCase;

Function<String,String> combined =
trim.andThen(upper);

Predicate chaining:

Predicate<Employee> active =
Employee::isActive;

Predicate<Employee> highSalary =
emp -> emp.getSalary() > 100000;

Predicate<Employee> eligible =
active.and(highSalary);

Question 15

Where are built-in Functional Interfaces used in Spring Boot?

Answer

Common use cases include:

  • Stream processing
  • DTO mapping
  • Repository filtering
  • Event listeners
  • Retry callbacks
  • Asynchronous processing
  • Security authorization
  • Validation logic
  • Kafka consumers
  • CompletableFuture pipelines

Question 16

Should we create custom Functional Interfaces?

Answer

Only when the built-in interfaces cannot clearly express the business requirement.

Prefer:

  • Predicate
  • Function
  • Consumer
  • Supplier

before creating custom interfaces.


Question 17

Which Functional Interface is used by Stream.filter()?

Answer

Predicate<T>

Example:

employees.stream()
         .filter(Employee::isActive);

Question 18

Which Functional Interface is used by Stream.map()?

Answer

Function<T,R>

Example:

employees.stream()
         .map(Employee::getName);

Question 19

Which Functional Interface is used by forEach()?

Answer

Consumer<T>

Example:

employees.forEach(System.out::println);

Question 20

Which Functional Interface is most commonly used in production?

Answer

The most commonly used are:

  • Predicate
  • Function
  • Consumer
  • Supplier

These four cover the majority of functional programming requirements in enterprise applications.


Real-Time Interview Scenario

Question

A Spring Boot application loads all employees, filters active records, converts them into DTOs, and logs each DTO.

Which Functional Interfaces are involved?

Answer

  • Predicate<Employee> → Filter active employees
  • Function<Employee, EmployeeDTO> → Convert entity to DTO
  • Consumer<EmployeeDTO> → Log or process each DTO

Best Practices

  • Prefer built-in Functional Interfaces over custom ones.
  • Use method references whenever they improve readability.
  • Use primitive Functional Interfaces for performance-critical code.
  • Keep Lambda expressions short and focused.
  • Chain Predicate and Function operations instead of writing nested logic.
  • Use meaningful variable names for Functional Interfaces.

Common Mistakes

❌ Creating unnecessary custom Functional Interfaces.

❌ Confusing Consumer with Function.

❌ Using Supplier when input parameters are required.

❌ Ignoring primitive Functional Interfaces in performance-sensitive applications.

❌ Writing long and complex Lambda expressions.


Interview Tips

Senior interviewers commonly ask:

  • Explain the differences between Predicate, Function, Consumer, and Supplier.
  • Why is UnaryOperator a specialization of Function?
  • When should you use BinaryOperator instead of BiFunction?
  • What are primitive Functional Interfaces, and why do they matter?
  • Which Functional Interfaces are used internally by the Stream API?
  • How are these interfaces used in Spring Boot?

Being able to identify the correct Functional Interface for a given problem is a strong indicator of Java expertise.


Summary

In this article, we covered:

  • Built-in Functional Interfaces
  • Predicate
  • Function
  • Consumer
  • Supplier
  • UnaryOperator
  • BinaryOperator
  • BiPredicate
  • BiFunction
  • BiConsumer
  • Primitive Functional Interfaces
  • Function chaining
  • Spring Boot production examples
  • Frequently asked interview questions
  • Best practices
  • Common mistakes

In the next article, we'll explore Functional Programming Best Practices, including immutability, avoiding side effects, debugging Lambdas, performance tuning, parallel streams, code review guidelines, and production-ready design principles.