findFirst vs findAny

Streams · lesson 18 of 42 · 3 min read

Both return an Optional match. Only one of them promises you the first element in order.

Open this lesson in the learning hub

Key points

  • findFirst returns the earliest match in encounter order, sequential or parallel. That promise costs coordination.
  • findAny returns whichever match some worker reached first. On a sequential stream that is almost always the first one too.
  • On a parallel stream findAny is the cheaper call, because no worker has to wait for the ones ahead of it.
  • Unordered sources such as HashSet have no encounter order, so the two behave the same there.
  • Both return Optional, so an empty result is a value you handle, never a null and never an exception.

Example

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

public class Main {
    public static void main(String[] args) {
        List<Integer> nums = IntStream.rangeClosed(1, 40).boxed().toList();

        System.out.println("findFirst seq : " + nums.stream().filter(n -> n % 5 == 0).findFirst().orElseThrow());
        System.out.println("findAny   seq : " + nums.stream().filter(n -> n % 5 == 0).findAny().orElseThrow());

        // In parallel findFirst still promises the first element in encounter order.
        System.out.println("findFirst par : " + nums.parallelStream().filter(n -> n % 5 == 0).findFirst().orElseThrow());

        // findAny is allowed to return any match, so run it many times and see what turns up.
        Set<Integer> seen = new TreeSet<>();
        for (int i = 0; i < 300; i++) {
            seen.add(nums.parallelStream().filter(n -> n % 5 == 0).findAny().orElseThrow());
        }
        System.out.println("findAny   par : saw " + seen + " over 300 runs");
        System.out.println("no match      : " + nums.stream().filter(n -> n > 99).findFirst().isPresent());
    }
}

Ask for findFirst only when the order genuinely matters.

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.