12.3 Lambda Expressions & Functional Interfaces
Lambda Expressions, introduced in Java 8, are a revolutionary feature that made Java dramatically more concise and modern. They made it possible to treat "nameless functions (anonymous functions)" as if they were data.
1. What is a Functional Interface?
To use lambda expressions, you need a Functional Interface— an interface that contains ** exactly one abstract method**. These are annotated with @FunctionalInterface.
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b); // Must have exactly one abstract method
}
2. Lambda Expression Syntax
// Old style (Anonymous class implementation)
Calculator add = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
// Lambda shorthand (much more concise!)
Calculator add = (a, b) -> a + b;
System.out.println(add.calculate(10, 20)); // 30
Lambda syntax rules:
- Format:
(parameters) -> returnExpression - Parentheses optional with a single parameter:
x -> x * 2 - Use curly braces for multi-line blocks:
(a, b) -> { ... return result; }
3. Java's Built-in Standard Functional Interfaces
Java pre-defines essential functional interfaces in the java.util.function package.
| Interface | Method | Description |
|---|---|---|
Predicate<T> | boolean test(T t) | Receives T, returns a boolean (condition check) |
Function<T,R> | R apply(T t) | Receives T, transforms it to type R |
Consumer<T> | void accept(T t) | Receives T, consumes it (no return value) |
Supplier<T> | T get() | Takes nothing, supplies a value of type T |
import java.util.function.*;
// Predicate: Check if a number is even
Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println(isEven.test(4)); // true
System.out.println(isEven.test(7)); // false
// Function: Return the length of a string
Function<String, Integer> getLength = s -> s.length();
System.out.println(getLength.apply("Hello")); // 5
// Consumer: A function that only prints
Consumer<String> printer = s -> System.out.println(">> " + s);
printer.accept("Java Lambda"); // >> Java Lambda
// Supplier: Supplies a value
Supplier<String> greeting = () -> "Hello, World!";
System.out.println(greeting.get()); // Hello, World!
4. Lambdas Meet Collections: A Taste of Streams
Lambda expressions become even more powerful when combined with collection methods like forEach() and removeIf().
import java.util.ArrayList;
ArrayList<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// Print all elements (lambda style)
names.forEach(name -> System.out.println("Name: " + name));
// Remove names with 3 or fewer characters
names.removeIf(name -> name.length() <= 3);
System.out.println(names); // [Alice, Charlie]
Lambda expressions and the Stream API are the most important modern Java features that dramatically elevated Java development productivity.