Java Lambda Expressions
Lambda expressions, introduced in Java 8, provide a concise and clean way to represent a functional interface (an interface with exactly one abstract method) as an expression. They enable a functional programming style in Java, reducing boilerplate code significantly.
Why Lambda Expressions?
Before Java 8, passing behavior (like defining what to do when a button is clicked) required creating anonymous inner classes, which were verbose. Lambda expressions replace this with a much shorter syntax.
Without Lambda (Before Java 8)
// Using an anonymous inner class
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("Task is running.");
}
};
task.run();With Lambda (Java 8+)
Runnable task = () -> System.out.println("Task is running.");
task.run();The lambda reduces five lines to one.
Lambda Syntax
(parameters) -> expression
(parameters) -> { statements; }- Parameters: The inputs to the method (can be empty
()or have types inferred). - Arrow (
->): Separates parameters from the body. - Body: A single expression or a block of statements.
Functional Interface
Lambda expressions work with functional interfaces — interfaces that have exactly one abstract method. The @FunctionalInterface annotation confirms this.
@FunctionalInterface
interface Greet {
void sayHello(String name);
}
public class Main {
public static void main(String[] args) {
Greet g = (name) -> System.out.println("Hello, " + name + "!");
g.sayHello("Alice"); // Hello, Alice!
}
}Lambda with Return Value
@FunctionalInterface
interface Multiplier {
int multiply(int a, int b);
}
public class Main {
public static void main(String[] args) {
Multiplier m = (a, b) -> a * b;
System.out.println("Result: " + m.multiply(6, 7)); // Result: 42
}
}Lambda with a Block Body
When the body has multiple statements, use curly braces and an explicit return.
@FunctionalInterface
interface Grade {
String evaluate(int marks);
}
public class Main {
public static void main(String[] args) {
Grade g = (marks) -> {
if (marks >= 90) return "A";
else if (marks >= 75) return "B";
else if (marks >= 60) return "C";
else return "F";
};
System.out.println(g.evaluate(88)); // B
System.out.println(g.evaluate(55)); // F
}
}Built-in Functional Interfaces (java.util.function)
Java 8 introduced the java.util.function package with commonly used functional interfaces.
Predicate<T> – Returns boolean
import java.util.function.Predicate;
Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println(isEven.test(4)); // true
System.out.println(isEven.test(7)); // falseFunction<T, R> – Takes input T, returns output R
import java.util.function.Function;
Function<String, Integer> strLength = s -> s.length();
System.out.println(strLength.apply("Hello")); // 5Consumer<T> – Takes input T, returns nothing
import java.util.function.Consumer;
Consumer<String> printUpperCase = s -> System.out.println(s.toUpperCase());
printUpperCase.accept("java"); // JAVASupplier<T> – Takes nothing, returns T
import java.util.function.Supplier;
Supplier<String> greeting = () -> "Welcome to Java 8!";
System.out.println(greeting.get()); // Welcome to Java 8!BiFunction<T, U, R> – Takes two inputs, returns output
import java.util.function.BiFunction;
BiFunction<Integer, Integer, Integer> power = (base, exp) -> (int) Math.pow(base, exp);
System.out.println(power.apply(2, 10)); // 1024Lambda with Collections – Sorting
Lambda expressions simplify sorting and processing collections.
import java.util.ArrayList;
import java.util.Collections;
ArrayList<String> names = new ArrayList<>();
names.add("Charlie");
names.add("Alice");
names.add("Bob");
// Sort alphabetically using lambda
Collections.sort(names, (a, b) -> a.compareTo(b));
System.out.println(names); // [Alice, Bob, Charlie]
// Sort by length
names.sort((a, b) -> a.length() - b.length());
System.out.println(names); // [Bob, Alice, Charlie]Lambda with forEach
import java.util.Arrays;
import java.util.List;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Using lambda with forEach
numbers.forEach(n -> System.out.print(n * n + " "));
// Output: 1 4 9 16 25Method Reference (Shorthand for Lambda)
When a lambda simply calls an existing method, it can be replaced with a method reference using the :: operator.
// Lambda
names.forEach(name -> System.out.println(name));
// Method reference – equivalent and cleaner
names.forEach(System.out::println);| Type | Syntax | Example |
|---|---|---|
| Static method | ClassName::methodName | Math::sqrt |
| Instance method (object) | object::methodName | System.out::println |
| Instance method (class) | ClassName::methodName | String::toUpperCase |
| Constructor | ClassName::new | ArrayList::new |
Summary
- Lambda expressions provide a short way to implement functional interfaces.
- Syntax:
(parameters) -> body - They work only with functional interfaces — interfaces with exactly one abstract method.
- Built-in functional interfaces in
java.util.function:Predicate,Function,Consumer,Supplier. - Lambda expressions simplify sorting, event handling, and collection processing.
- Method references (
::) are a clean shorthand when a lambda just calls an existing method.
