Lambdas and Functional Interfaces in Java Explained
Learn Java lambdas the easy way — pass code as a value, understand functional interfaces, lambda syntax, and built-ins like Predicate, Function, Consumer and Supplier.
Welcome to Level 4 — modern Java. This is where the language becomes genuinely elegant and fun to write. We start with lambdas: a compact way to pass behaviour (a chunk of code) around as if it were data. Lambdas power the Streams API you'll learn next, and once they click, your code gets dramatically shorter and clearer. Don't worry if this feels new — we'll build it up gently.
The idea: code as a value
Until now, you've passed data to methods — numbers, strings, objects. A lambda lets you pass a small piece of code instead. Think "here's a short instruction, go run it when you need to." This is incredibly handy for things like "do this for each item" or "sort using this rule."
The old way vs the lambda way
Before lambdas (Java 8), passing behaviour meant writing a bulky anonymous class. Watch how much a lambda trims away. Here's running some code with a Runnable:
// OLD way — verbose anonymous class Runnable r1 = new Runnable() { @Override public void run() { System.out.println("Hello!"); } }; // NEW way — a lambda. Same thing! Runnable r2 = () -> System.out.println("Hello!");
Both do exactly the same thing — the lambda just strips away all the ceremony, leaving only what matters.
Lambda syntax
A lambda has three parts: parameters, an arrow ->, and a body.
(parameters) -> { body }
// examples:
() -> System.out.println("Hi") // no parameters
x -> x * 2 // one parameter, returns x*2
(a, b) -> a + b // two parameters, returns their sum
(a, b) -> { return a + b; } // same, with an explicit body + return
Short bodies don't need braces or return — Java figures it out. For single parameters you can even drop the parentheses. It's all designed to keep things tidy.
Functional interfaces: what a lambda actually is
Here's the key concept. A lambda is really an implementation of a functional interface — an interface with exactly one abstract method. Because there's only one method to implement, Java lets you skip all the boilerplate and just write the body as a lambda.
@FunctionalInterface interface Calculator { int operate(int a, int b); // exactly one abstract method } // a lambda IS the implementation of that one method: Calculator add = (a, b) -> a + b; Calculator multiply = (a, b) -> a * b; System.out.println(add.operate(3, 4)); // 7 System.out.println(multiply.operate(3, 4)); // 12
Built-in functional interfaces
Java provides ready-made functional interfaces so you rarely define your own. The main ones:
| Interface | Takes → Returns | Use |
|---|---|---|
Predicate<T> |
T → boolean | A test/condition |
Function<T,R> |
T → R | Transform a value |
Consumer<T> |
T → nothing | Do something with it |
Supplier<T> |
nothing → T | Provide a value |
A taste of where this shines
Lambdas make collection operations beautifully readable. This is a preview of the Streams API — the very next lesson:
List<String> names = List.of("Asha", "Ravi", "Sam"); names.forEach(name -> System.out.println(name)); // print each names.sort((a, b) -> a.length() - b.length()); // sort by length
Lambdas were the feature that made Java feel modern to me after years of verbose anonymous classes. The first time I replaced a ten-line anonymous class with a one-line lambda, the code didn't just get shorter — it got clearer, because only the essential logic remained. They take a little getting used to, but they unlock the most enjoyable, expressive part of modern Java, which we'll dive into next with streams.
Key takeaways
- A lambda lets you pass a piece of code (behaviour) as a value:
(params) -> body. - It's shorthand for implementing a functional interface — one with a single abstract method.
- Java provides built-ins:
Predicate,Function,Consumer,Supplier. - Lambdas make working with collections far more concise — the foundation of the Streams API.
← Previous: Lesson 26 — Immutability in Java
Next: Lesson 28 — The Streams API →