Java Lambda Expressions
Java lambda expressions are short, anonymous functions you can pass around like values. Added in Java 8, they make code that sorts, filters or reacts to events far more concise.
Lambda Syntax
- (parameters) -> expression, for example (a, b) -> a + b
- A single parameter needs no parentheses: x -> x * 2
- No parameters: () -> System.out.println("hi")
- Multiple statements need braces and return: (x) -> { int y = x * 2; return y + 1; }
Functional Interfaces
A lambda always implements a functional interface, an interface with exactly one abstract method. java.util.function provides common ones so you rarely need to write your own.
import java.util.function.*;
public class Main {
public static void main(String[] args) {
Predicate<Integer> isEven = n -> n % 2 == 0;
Function<String, Integer> length = s -> s.length();
Consumer<String> shout = s -> System.out.println(s.toUpperCase() + "!");
Supplier<Double> random = () -> 4.0; // pretend random
BinaryOperator<Integer> multiply = (a, b) -> a * b;
System.out.println(isEven.test(10));
System.out.println(length.apply("lambda"));
shout.accept("hello");
System.out.println(random.get());
System.out.println(multiply.apply(6, 7));
}
}true 6 HELLO! 4.0 42
Lambdas with Collections
Many collection methods accept lambdas, which replaces whole loops with one readable line.
import java.util.*;
public class Main {
public static void main(String[] args) {
List<String> cities = new ArrayList<>(List.of("Karachi", "Oslo", "Dubai", "Lima"));
cities.sort((a, b) -> a.length() - b.length());
System.out.println(cities);
cities.removeIf(c -> c.startsWith("L"));
cities.forEach(c -> System.out.println("City: " + c));
Map<String, Integer> scores = new TreeMap<>(Map.of("Ali", 80, "Zoya", 92));
scores.forEach((name, score) -> System.out.println(name + " scored " + score));
}
}[Oslo, Lima, Dubai, Karachi] City: Oslo City: Dubai City: Karachi Ali scored 80 Zoya scored 92
List.sort is stable, so Oslo and Lima (both four letters) keep their original order.
Method References
When a lambda just calls an existing method, a method reference using :: is even shorter.
import java.util.List;
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
List<String> words = List.of("alpha", "beta");
words.forEach(System.out::println); // s -> System.out.println(s)
Function<String, Integer> parse = Integer::parseInt; // s -> Integer.parseInt(s)
Function<String, String> upper = String::toUpperCase;
System.out.println(parse.apply("21") * 2);
System.out.println(upper.andThen(s -> s + "?").apply("why"));
}
}alpha beta 42 WHY?
Variable Capture
A lambda can use local variables from the surrounding method, but only if they are effectively final, meaning they are never reassigned after being set.
Frequently asked questions
What is a functional interface in Java?
An interface with exactly one abstract method, such as Runnable, Comparator or Predicate. Any lambda can be used where a functional interface is expected.
What does :: mean in Java?
It creates a method reference, a shorthand for a lambda that only calls one method, like String::length instead of s -> s.length().
Why must variables used in a lambda be effectively final?
The lambda may run later or on another thread, so Java captures a copy of the value. Forbidding reassignment avoids confusing behaviour where the copy and the original differ.