Skip to main content

Lambdas, Functional Interfaces and Streams

Lambdas​

A lambda is a short anonymous function that implements a functional interface (one abstract method).

import java.util.*;

List<String> names = new ArrayList<>(List.of("Ravi", "Asha", "Meera"));

names.sort((a, b) -> a.length() - b.length()); // Comparator lambda
names.forEach(n -> System.out.println(n));
names.forEach(System.out::println); // method reference

Built-in functional interfaces​

InterfaceMethodExample
Predicate<T>boolean test(T)s -> s.isEmpty()
Function<T,R>R apply(T)String::length
Consumer<T>void accept(T)System.out::println
Supplier<T>T get()() -> new ArrayList<>()
BiFunction<T,U,R>R apply(T,U)Integer::sum
UnaryOperator<T>T apply(T)String::trim

The Stream API​

A stream is a pipeline: source -> intermediate operations -> terminal operation.

import java.util.stream.*;

record Student(String name, String dept, int marks) {}

List<Student> students = List.of(
new Student("Asha", "CS", 91), new Student("Ravi", "EE", 74),
new Student("Meera", "CS", 88), new Student("Kabir", "ME", 69));

// names of CS students scoring above 85, sorted
List<String> top = students.stream()
.filter(s -> s.dept().equals("CS"))
.filter(s -> s.marks() > 85)
.map(Student::name)
.sorted()
.collect(Collectors.toList()); // [Asha, Meera]

// average marks per department
Map<String, Double> avg = students.stream()
.collect(Collectors.groupingBy(Student::dept, Collectors.averagingInt(Student::marks)));

// total, max
int total = students.stream().mapToInt(Student::marks).sum();
Optional<Student> best = students.stream().max(Comparator.comparingInt(Student::marks));

Key operations​

OperationTypeNotes
filter, map, flatMap, sorted, distinct, limitIntermediate (lazy)Nothing runs until a terminal operation
collect, forEach, reduce, count, anyMatchTerminalTriggers execution
parallelStream()-Only for large, CPU-bound, side-effect-free work
CAUTION

Do not mutate shared state inside stream lambdas, and do not reuse a stream: it can be consumed only once.