Lambdas & Streams

A lambda expression is a compact way to write an anonymous function — a small block of behavior you can pass around like a value, without writing a whole named method or class for it. Paired with the Stream API, lambdas let you process collections of data in a readable, chainable style.

What Is a Lambda Expression?

A lambda has the shape (parameters) -> expression (or a block in braces). It only makes sense where Java expects a functional interface — an interface with exactly one abstract method — because the lambda is really just a shorthand implementation of that one method.

Example: A Simple Runnable Lambda

public class LambdaDemo {
  public static void main(String[] args) {
    Runnable r = () -> System.out.println("Running!");
    r.run();
  }
}

Here, () -> System.out.println("Running!") implements Runnable's single abstract method, run(), without ever writing a class or an @Override. Lambdas show up constantly with Comparator too — for example, sorting a list of strings by length:

names.sort((a, b) -> a.length() - b.length());
          

The Stream API

A stream is a pipeline for processing a sequence of elements — usually the contents of a collection — through a chain of operations like filter, map, and collect, instead of a manual for loop with intermediate variables.

Example: Filter, Map, Collect

import java.util.List;
import java.util.stream.Collectors;

public class StreamDemo {
  public static void main(String[] args) {
    List<String> names = List.of("Sonu", "Amit", "Riya", "Om");

    List<String> result = names.stream()
      .filter(name -> name.length() > 2)
      .map(String.valueOf)
      .map(name -> name.toUpperCase())
      .collect(Collectors.toList());

    System.out.println(result); // [SONU, AMIT, RIYA]
  }
}

What's happening:

  • .stream() turns the list into a stream you can chain operations onto.
  • .filter(...) keeps only elements matching a condition — here, names longer than 2 characters.
  • .map(...) transforms each remaining element — here, converting it to uppercase.
  • .collect(Collectors.toList()) gathers the final results back into a List.

Why Streams Are Useful

The same logic written with a manual loop would need a temporary result list, an if check inside the loop, and a call to add each transformed item. The stream version reads top-to-bottom as a description of what should happen to the data, rather than the low-level bookkeeping of how to loop through it. Chained stream operations are also easy to reorder, add to, or remove without restructuring loop logic.

Next up: learn about fixed sets of named constants with Enums.