Replace anonymous classes with concise lambda syntax — the shift to functional Java.
Published February 1, 2025
Lambdas are anonymous functions — a concise way to pass behaviour as data.
list.sort(new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
list.sort((a, b) -> a.compareTo(b));
// Or even shorter with method reference:
list.sort(String::compareTo);
A lambda can only be used where a functional interface (interface with exactly one abstract method) is expected.
| Interface | Signature | Use Case |
|---|---|---|
Runnable | () → void | Run a task |
Supplier<T> | () → T | Produce a value |
Consumer<T> | T → void | Consume a value |
Function<T,R> | T → R | Transform a value |
Predicate<T> | T → boolean | Test a condition |
BiFunction<T,U,R> | (T,U) → R | Two-argument transform |
Predicate<String> isLong = s -> s.length() > 5;
Function<String, Integer> length = String::length;
Consumer<String> printer = System.out::println;
Supplier<List<String>> newList = ArrayList::new;
Lambdas can capture local variables, but only if they are effectively final (never modified after assignment):
String prefix = "Hello, ";
Consumer<String> greet = name -> System.out.println(prefix + name); // ✅
prefix = "Hi, "; // ❌ compile error: prefix must be effectively final
Know the four core functional interfaces (Supplier, Consumer, Function, Predicate) and when to use each. Interviewers also test whether you understand that lambdas don't create a new scope — this inside a lambda refers to the enclosing class, not the lambda.