Advanced Java August 19 ,2025

Java Functional Interfaces

1. Introduction

A functional interface in Java is an interface that contains exactly one abstract method (also known as a Single Abstract Method or SAM interface).

  • From Java 8 onwards, functional interfaces became the foundation for Lambda Expressions and Method References, allowing Java to support functional-style programming.
  • A functional interface may include multiple default or static methods, but only one abstract method.

Examples of Functional Interfaces

  • Runnable (method run())
  • Callable (method call())
  • Comparator (method compare())
  • Predicate, Function, Consumer, Supplier (introduced in Java 8)

2. Using Functional Interfaces with Lambda Expressions

A lambda expression provides a clear and concise way to implement the abstract method of a functional interface.

Example – Runnable with Lambda

public class Geeks {
    public static void main(String[] args) {
        // Using lambda expression to implement Runnable
        new Thread(() -> System.out.println("New thread created")).start();
    }
}

Output:

New thread created

Explanation:

  • Runnable is a functional interface with one method run().
  • The lambda () -> System.out.println("New thread created") is the implementation of run().
  • When the thread starts, it executes the lambda body.

3. @FunctionalInterface Annotation

The @FunctionalInterface annotation is used to mark an interface as functional.

  • It ensures that the interface has only one abstract method.
  • If more than one abstract method is declared, the compiler throws an error.
  • Although optional, it is best practice to use this annotation.

Example

@FunctionalInterface
interface Square {
    int calculate(int x);
}

class Geeks {
    public static void main(String args[]) {
        int a = 5;

        // Lambda expression implementing calculate()
        Square s = (int x) -> x * x;

        System.out.println(s.calculate(a));
    }
}

Output:

25

4. Functional Interfaces Before Java 8

Before Java 8, functional interfaces were implemented using anonymous inner classes.

Example

class Geeks {
    public static void main(String args[]) {
        // Anonymous inner class implementation
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("New thread created");
            }
        }).start();
    }
}

Output:

New thread created

Observation:

  • This approach is verbose compared to Java 8’s lambda syntax.
  • Lambda expressions make functional interface usage much cleaner.

5. Built-in Functional Interfaces

Java 8 introduced the package java.util.function, which provides many ready-to-use functional interfaces. These interfaces are designed to work with lambda expressions and method references, making code more concise and expressive.

Apart from java.util.function, some older interfaces from java.lang (like Runnable and Comparable) also qualify as functional interfaces because they have only one abstract method (SAM – Single Abstract Method).

Common Built-in Functional Interfaces

Functional InterfaceMethod SignaturePurpose
Runnablevoid run()Represents a task to be executed in a thread (no input, no output).
CallableV call()Similar to Runnable but can return a result and throw exceptions.
Comparableint compareTo(T o)Compares two objects for ordering.
Predicateboolean test(T t)Takes an input and returns a boolean (used in conditions/filters).
Consumervoid accept(T t)Consumes an input, performs an action, but does not return.
SupplierT get()Supplies a value without taking input.
FunctionR apply(T t)Takes input and produces a result (used in transformations).

6. Types of Functional Interfaces

Java 8 broadly categorizes functional interfaces into four major types:

6.1 Consumer

  • Theory:
    A Consumer takes one input argument but does not return any result. It is generally used for performing operations on the given input such as printing, logging, or modifying objects.
  • Method:

    void accept(T t)
    
  • Example:

    import java.util.function.Consumer;
    
    class Demo {
        public static void main(String[] args) {
            Consumer consumer = (value) -> System.out.println("Value: " + value);
            consumer.accept(10); // prints Value: 10
        }
    }
    
  • Output:

    Value: 10
    
  • Variants:
    • IntConsumer, DoubleConsumer, LongConsumer – work with primitives.
    • BiConsumer – accepts two inputs and returns nothing.

6.2 Predicate

  • Theory:
    A Predicate takes one argument and returns a boolean result. It is widely used for filtering data, conditional checks, and stream operations.
  • Method:

    boolean test(T t)
    
  • Example: Filtering strings starting with "G".

    import java.util.*;
    import java.util.function.Predicate;
    
    class Demo {
        public static void main(String[] args) {
            List list = Arrays.asList("Geek", "GeeksQuiz", "g1", "QA", "Geek2");
    
            Predicate p = (s) -> s.startsWith("G");
    
            for (String str : list) {
                if (p.test(str)) {
                    System.out.println(str);
                }
            }
        }
    }
    
  • Output:

    Geek
    GeeksQuiz
    Geek2
    
  • Variants:
    • IntPredicate, DoublePredicate, LongPredicate – work with primitives.
    • BiPredicate – takes two inputs and returns a boolean.

6.3 Function

  • Theory:
    A Function takes one input and produces one result. It is useful for data transformation (e.g., converting, mapping, or processing values).
  • Method:

    R apply(T t)
    
  • Example: Squaring a number.

    import java.util.function.Function;
    
    class Demo {
        public static void main(String[] args) {
            Function function = x -> x * x;
            System.out.println(function.apply(5)); // 25
        }
    }
    
  • Output:

    25
    
  • Variants:
    • BiFunction – takes two inputs and returns one output.
    • UnaryOperator – takes one input and returns the same type.
    • BinaryOperator – takes two inputs of the same type and returns the same type.

6.4 Supplier

  • Theory:
    A Supplier provides a value without requiring any input. It is often used for lazy evaluation, object creation, or data generation.
  • Method:

    T get()
    
  • Example: Returning a string.

    import java.util.function.Supplier;
    
    class Demo {
        public static void main(String[] args) {
            Supplier supplier = () -> "Hello, World!";
            System.out.println(supplier.get());
        }
    }
    
  • Output:

    Hello, World!
    
  • Variants:
    • BooleanSupplier, IntSupplier, DoubleSupplier, LongSupplier – return primitive values.

7. Extended Functional Interfaces

  • BiConsumer → Accepts two inputs, no return.
  • BiPredicate → Accepts two inputs, returns boolean.
  • BiFunction → Accepts two inputs, returns result.
  • UnaryOperator → Special case of Function where input and output types are the same.
  • BinaryOperator → Special case of BiFunction where both inputs and output are the same type.

8. Functional Interfaces in Streams

Functional interfaces are widely used in Java Streams API for functional-style operations.

Example – Using Predicate and Consumer with Streams:

import java.util.*;
import java.util.stream.*;

class Geeks {
    public static void main(String[] args) {
        List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

        numbers.stream()
               .filter(n -> n % 2 == 0)       // Predicate
               .forEach(n -> System.out.println(n)); // Consumer
    }
}

Output:

2
4
6

9. Functional Interfaces Summary Table

Functional InterfaceDescriptionMethodExample
RunnableRepresents a task executed by a threadvoid run()new Thread(() -> {...}).start();
CallableTask that returns resultV call()Callable c = () -> 5;
ComparableCompares two objectsint compareTo(T o)s1.compareTo(s2)
ConsumerAccepts input, returns nothingvoid accept(T t)Consumer c = x -> ...;
PredicateAccepts input, returns booleanboolean test(T t)Predicate p = s -> ...;
FunctionInput → ResultR apply(T t)Function f = x -> x*x;
SupplierNo input, returns resultT get()Supplier s = () -> "Hi";
BiConsumerTwo inputs, no resultvoid accept(T, U)(a,b)->System.out.println(a+b)
BiPredicateTwo inputs, boolean resultboolean test(T,U)(a,b)->a>b
BiFunctionTwo inputs, one resultR apply(T,U)(a,b)->a+b
UnaryOperatorInput & output sameT apply(T t)x -> x*x
BinaryOperatorTwo inputs, output same typeT apply(T,T)(a,b)->a+b

10. Key Takeaways

  1. A functional interface has exactly one abstract method.
  2. Lambda expressions and method references rely on functional interfaces.
  3. Java provides built-in functional interfaces in java.util.function.
  4. Major types: Consumer, Predicate, Function, Supplier.
  5. Extensively used in multithreading, event handling, and the Streams API.

 

Next Blog- Java Stream API

 

 

Sanjiv
0

You must logged in to post comments.

Related Blogs

Generics P...
Advanced Java August 08 ,2025

Generics Part- 2

Collection...
Advanced Java July 07 ,2025

Collections Framewor...

Mastering...
Advanced Java August 08 ,2025

Mastering Java Multi...

Annotation...
Advanced Java August 08 ,2025

Annotations

Java Memor...
Advanced Java August 08 ,2025

Java Memory Manageme...

Java Lambd...
Advanced Java August 08 ,2025

Java Lambda Expressi...

Java Strea...
Advanced Java August 08 ,2025

Java Stream API

JDBC (Java...
Advanced Java August 08 ,2025

JDBC (Java Database...

JDBC (Java...
Advanced Java September 09 ,2025

JDBC (Java Database...

Annotation...
Advanced Java August 08 ,2025

Annotations

Generics
Advanced Java August 08 ,2025

Generics

Java I/O (...
Advanced Java August 08 ,2025

Java I/O (NIO)

Introducti...
Advanced Java September 09 ,2025

Introduction to Desi...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Other Prin...
Advanced Java September 09 ,2025

Other Principles Beh...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Builder De...
Advanced Java September 09 ,2025

Builder Design Patte...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Chain of R...
Advanced Java September 09 ,2025

Chain of Responsibil...

Command De...
Advanced Java September 09 ,2025

Command Design Patte...

Interprete...
Advanced Java September 09 ,2025

Interpreter Design P...

Iterator D...
Advanced Java September 09 ,2025

Iterator Design Patt...

Mediator D...
Advanced Java September 09 ,2025

Mediator Design Patt...

Memento De...
Advanced Java September 09 ,2025

Memento Design Patte...

Observer D...
Advanced Java September 09 ,2025

Observer Design Patt...

State Desi...
Advanced Java September 09 ,2025

State Design Pattern...

Strategy D...
Advanced Java September 09 ,2025

Strategy Design Patt...

Template M...
Advanced Java September 09 ,2025

Template Method Desi...

Visitor De...
Advanced Java September 09 ,2025

Visitor Design Patte...

Prototype...
Advanced Java September 09 ,2025

Prototype Design Pat...

Java 8+ Fe...
Advanced Java October 10 ,2025

Java 8+ Features

SOLID Prin...
Advanced Java October 10 ,2025

SOLID Principles in...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

How Iterat...
Advanced Java October 10 ,2025

How Iterators Work i...

How Concur...
Advanced Java October 10 ,2025

How ConcurrentHashMa...

Comparable...
Advanced Java October 10 ,2025

Comparable vs Compar...

Semaphore...
Advanced Java October 10 ,2025

Semaphore in Java

Get In Touch

G06, Kristal Olivine Bellandur near Bangalore Central Mall, Bangalore Karnataka, 560103

+91-8076082435

techiefreak87@gmail.com