Syllabus / Java / Phase 5: Advanced Java — Streams, Lambda, Multithreading, DB (Days 22–26)
Intermediate

Lambda Expressions and Functional Interfaces

📂 Phase 5: Advanced Java — Streams, Lambda, Multithreading, DB (Days 22–26) · Java

Lambda expressions, introduced in Java 8, let you write concise, functional-style code by treating behavior as data — passing a block of logic as if it were a value, without the boilerplate of an anonymous class.

Before Lambdas: The Anonymous Class Way

// Old way — verbose
Runnable task = new Runnable() {
    @Override
    public void run() {
        System.out.println("Running task");
    }
};

The Lambda Equivalent

// New way — concise
Runnable task = () -> System.out.println("Running task");

Functional Interfaces — The Foundation of Lambdas

A lambda expression can only be used where a functional interface is expected — an interface with exactly one abstract method.

@FunctionalInterface
interface Greeting {
    String sayHello(String name);
}

Greeting greeting = (name) -> "Hello, " + name;
System.out.println(greeting.sayHello("Vishwas")); // Hello, Vishwas
The @FunctionalInterface annotation is optional, but recommended — if someone later adds a second abstract method to that interface, the compiler immediately flags an error instead of letting it silently break.

Common Built-In Functional Interfaces

InterfaceMethodUse Case
Function<T,R>R apply(T t)Transform one value into another
Predicate<T>boolean test(T t)Test a condition, return true/false
Consumer<T>void accept(T t)Perform an action, no return value
Supplier<T>T get()Produce a value with no input

Using Lambdas with the Collections Framework

List names = Arrays.asList("John", "Jane", "Doe");
names.forEach(name -> System.out.println(name));

Predicate isEven = num -> num % 2 == 0;
System.out.println(isEven.test(4)); // true

Important Restriction: Effectively Final Variables

A lambda can access local variables from its enclosing scope, but only if they are effectively final — never reassigned after initialization.

int count = 5;
Runnable r = () -> System.out.println(count); // OK
count = 10; // ERROR — count is no longer effectively final once reassigned
Interview tip: "Can a lambda replace any anonymous class?" — No. Lambdas can only implement functional interfaces (single abstract method). Anonymous classes can implement interfaces with multiple methods or extend abstract classes — lambdas cannot.