Optional and Streams

Streams · lesson 12 of 42 · 3 min read

Handle the maybe-nothing results streams hand back, and flatten Optionals away.

Open this lesson in the learning hub

Key points

  • findFirst, findAny, min, max and single-argument reduce all return an Optional.
  • An Optional means maybe nothing. It is not a wrapper for null.
  • Prefer orElse, orElseGet, orElseThrow and ifPresentOrElse over calling get().
  • Optional.stream() (Java 9+) turns 0-or-1 into a stream, so flatMap(Optional::stream) drops the empties.
  • findAny is cheaper on parallel streams. findFirst forces encounter order.

Example

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        List<String> names = List.of("ada", "grace", "alan");

        Optional<String> first = names.stream().filter(n -> n.startsWith("g")).findFirst();
        Optional<String> longest = names.stream().max(Comparator.comparingInt(String::length));
        Optional<String> missing = names.stream().filter(n -> n.startsWith("z")).findFirst();

        System.out.println("first   : " + first.orElse("none"));
        System.out.println("longest : " + longest.orElseThrow());
        System.out.println("missing : " + missing.orElse("none"));
        System.out.println("mapped  : " + first.map(String::toUpperCase).orElse("none"));
        missing.ifPresentOrElse(
                n -> System.out.println("found " + n),
                () -> System.out.println("nothing starts with z"));

        // Optional.stream() (Java 9+): 0-or-1 becomes a stream, so empties disappear.
        List<String> known = Stream.of("ada", "zoe", "alan")
                .map(n -> names.contains(n) ? Optional.of(n) : Optional.<String>empty())
                .flatMap(Optional::stream)
                .toList();
        System.out.println("known   : " + known);
    }
}

Optional is the compiler reminding you the stream might be empty.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.