Stream.findFirst în Java

Returnează primul element din stream (findFirst) sau oricare element (findAny), ca Optional.

Sintaxă
Optional<T> findFirst()
Optional<T> findAny()

Ce face Stream.findFirst

findFirst() returnează primul element al stream-ului, de obicei după un filter: „primul student cu nota 10”. Stream-ul se oprește imediat ce l-a găsit. Rezultatul este un Optional, gol dacă nu există niciun element.

findAny() returnează un element oarecare. Pe un stream secvențial dă de obicei tot primul element, dar nu este o garanție; pe un stream paralel poate da altul la fiecare rulare. Folosește-l doar când nu contează care element vine.

Ce returnează

Un Optional<T> cu elementul găsit sau gol.

Exemple

Exemplul 1: Primul student cu nota 10

import java.util.List;
import java.util.Optional;

public class Main {
    record Student(String nume, int nota) {}

    public static void main(String[] args) {
        List<Student> grupa = List.of(
                new Student("Radu", 8), new Student("Ioana", 10),
                new Student("Ana", 10), new Student("Dan", 6));

        Optional<Student> primul = grupa.stream().filter(s -> s.nota() == 10).findFirst();
        System.out.println(primul.map(Student::nume).orElse("nimeni"));

        String cu4 = grupa.stream().filter(s -> s.nota() == 4)
                .map(Student::nume).findFirst().orElse("nimeni");
        System.out.println("Cu nota 4: " + cu4);
    }
}

Rezultat

Ioana
Cu nota 4: nimeni

Exemplul 2: findAny: când orice element e bun

Vrem doar să știm un oraș cu peste 200.000 de locuitori, oricare. Rezultatul aici este deterministic pentru că verificăm doar dacă există.

import java.util.List;

public class Main {
    record Oras(String nume, int locuitori) {}

    public static void main(String[] args) {
        List<Oras> orase = List.of(new Oras("Iași", 271_000), new Oras("Cluj", 286_000), new Oras("Arad", 145_000));
        boolean areMare = orase.parallelStream()
                .filter(o -> o.locuitori() > 200_000)
                .findAny()
                .isPresent();
        System.out.println("Există un oraș mare: " + areMare);
    }
}

Rezultat

Există un oraș mare: true

Greșeli frecvente

  • Folosești findAny pe un stream paralel și aștepți primul element. Folosește findFirst.
  • Apelezi get() pe rezultat fără să verifici că există. Pentru „nu am găsit” folosește orElse.
  • Primul element este null: findFirst aruncă NullPointerException, pentru că un Optional nu poate conține null.

Comenzi înrudite

  • Stream.filter: Păstrează în stream doar elementele care îndeplinesc o condiție.
  • Stream.anyMatch: Verifică dacă cel puțin un element (anyMatch), toate (allMatch) sau niciunul (noneMatch) nu îndeplinesc o condiție.
  • Stream.limit: limit păstrează doar primele n elemente, iar skip sare peste primele n.
  • Stream.min / Stream.max: Găsesc cel mai mic și cel mai mare element după un Comparator; rezultatul este un Optional.