Lambdas and Functional Interfaces
Pass behaviour as data with lambda expressions and method references.
What you’ll learn
- What a functional interface is
- Lambda syntax and method references
- Predicate, Function, Consumer and Supplier
- Effectively final variables
Behaviour as a value
Before Java 8, passing behaviour to a method meant writing an anonymous class:
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.length() - b.length();
}
});With a lambda, that becomes:
names.sort((a, b) -> a.length() - b.length());Same behaviour, a fraction of the noise.
Functional interfaces
A lambda can be used anywhere Java expects a functional interface — an interface with exactly one abstract method. Comparator, Runnable and the types in java.util.function are all functional interfaces.
| Interface | Signature | Use it for |
|---|---|---|
Predicate<T> | T -> boolean | Tests / filters |
Function<T, R> | T -> R | Transformations |
Consumer<T> | T -> void | Side effects (print, save) |
Supplier<T> | () -> T | Lazy creation |
Predicate<String> isLong = s -> s.length() > 5;
Function<String, Integer> length = s -> s.length();
Consumer<String> printer = s -> System.out.println(s);
Supplier<List<String>> fresh = () -> new ArrayList<>();Lambda syntax
x -> x * 2 // one parameter, expression body
(a, b) -> a + b // multiple parameters
() -> "hello" // no parameters
(String s) -> s.isBlank() // explicit type
order -> { // block body needs return
var tax = order.total() * 0.18;
return order.total() + tax;
}Method references
When a lambda only calls an existing method, use a method reference:
names.forEach(s -> System.out.println(s));
names.forEach(System.out::println); // same thing
names.stream().map(s -> s.toUpperCase());
names.stream().map(String::toUpperCase); // same thingEffectively final
Lambdas can read local variables from the surrounding method only if those variables are never reassigned (effectively final). This prevents confusing bugs, especially with concurrent code.
⚡ Try it yourself
Write a method List<String> filter(List<String> input, Predicate<String> rule) and call it three ways: words starting with "S", words longer than 4 characters, and non-blank words.
Interview questions
QWhat is a functional interface? Can you create your own?+
An interface with exactly one abstract method. Yes — just declare one, ideally annotated with @FunctionalInterface so the compiler enforces the single-method rule.
Key takeaways
- Lambdas are concise implementations of functional interfaces.
- Learn the four core types: Predicate, Function, Consumer, Supplier.
- Use method references (
Class::method) when they read better.
Finished this lesson?
Mark it complete to move forward on your roadmap.