8.1 Lambda Expressions
← Back to Chapter 8: Java 8 Features
Lambda expressions, introduced in Java 8, bring functional programming capabilities to Java. They provide a clear and concise way to represent single-method interfaces (Functional Interfaces) using an expression.
What is a Lambda Expression?
A lambda expression is an anonymous function — a function without a declared name, return type, or explicit access modifiers. It can be passed around as if it were an object and executed on demand.
(parameters) -> { expression or statements }
▲ ▲ ▲
│ │ │
Argument Lambda Body / Logic
List Operator
Suppose we have a simple interface:
@FunctionalInterface
interface Calculator {
int add(int a, int b);
}
Before Java 8, we could implement it using an anonymous class:
Calculator calculator = new Calculator() {
@Override
public int add(int a, int b) {
return a + b;
}
};
This is a lot of code for such a simple operation.
With Lambda:
Calculator calculator = (a, b) -> a + b;
That's the main purpose of Lambda:
Remove unnecessary boilerplate code and make it easy to pass behavior as a value.
Without Lambda:
Object → Class → Method → Behavior
With Lambda:
Object → Behavior
That's why Lambda is so useful with:
Streams
Collections
Functional interfaces
CompletableFuture
Event handling
Spring code
Different Lambda forms
No/Zero Parameter
// 1. Zero arguments
() -> System.out.println("Hello, Java 8!");
Single Parameter
// 2. Single parameter (type inference allows omitting parentheses and type)
name -> System.out.println("Hello, " + name);
Parentheses are optional for one parameter.
(name) -> System.out.println(name);
Multiple Parameters
// 3. Multiple parameters with explicit types
(int a, int b) -> a + b;
Multiple Parameters with Inferred Types
// 4. Multiple parameters with inferred types (most common)
(a, b) -> a + b;
Multi-line Body
// 5. Multi-line body (requires curly braces and explicit return if returning a value)
(a, b) -> {
int sum = a + b;
System.out.println("Sum: " + sum);
return sum;
};
When using { }, if the Lambda needs to return a value, you normally use return.
Lambda does NOT have a type by itself
You cannot normally do:
var x = () -> System.out.println("Hello");
because a Lambda needs a target functional interface type.
For example:
Runnable r = () -> System.out.println("Hello");
Here Java knows:
Lambda
↓
Runnable
↓
run()
That's how Java understands what the Lambda represents.
Why Functional Interface is required
A Lambda represents the implementation of one abstract method.
Lambda and Variable Scope
Suppose:
int number = 10;
Runnable r = () -> {
System.out.println(number);
};
This is allowed.
But if you try:
int number = 10;
number = 20;
Runnable r = () -> {
System.out.println(number);
};
This is not allowed.
Why?
Because a local variable used inside a Lambda must be final or effectively final.
What does effectively final mean?
It means: You don't have to explicitly write final, but you must not change the variable after assigning it.
Modern Java 8 Lambda:
Runnable r2 = () -> System.out.println("Thread running via Lambda");
| Aspect | Anonymous Inner Class | Lambda Expression |
|---|---|---|
| Boilerplate | High (class declaration, method signature) | Minimal (parameters and arrow body) |
| Bytecode Generation | Creates separate .class file (Outer$1.class) | Uses invokedynamic (no extra class file) |
this Keyword | Refers to the inner class instance itself | Lexically scoped: refers to enclosing class |
| Target | Can implement interfaces or extend abstract/concrete classes | Can only implement Functional Interfaces |
| Performance | Higher memory footprint and classloader overhead | Lower memory footprint, faster startup |
Version wise updates
| Java Version | Lambda-related change |
|---|---|
| Java 8 | ⭐ Lambda introduced |
| Java 9 | No major Lambda change |
| Java 10 | var introduced for local variables, not Lambda parameters |
| Java 11 | ⭐ var allowed in Lambda parameters |
| Java 12–17 | No major Lambda change |
| Java 18–20 | No major Lambda change |
| Java 21 | No major Lambda change |
| Java 22–24 | No major Lambda change |
| Java 25 | No major Lambda change |
| Java 26 | No major Lambda change |