Stream.filter în Java

Păstrează în stream doar elementele care îndeplinesc o condiție.

Sintaxă
Stream<T> filter(Predicate<? super T> conditie)

Ce face Stream.filter

filter(conditie) trece fiecare element prin condiție (un Predicate, de obicei scris ca lambda). Elementele pentru care condiția este true merg mai departe; celelalte sunt eliminate. Ordinea se păstrează.

Poți înlănțui mai multe filter sau poți combina condițiile cu && și || în aceeași lambda. Pentru condiții refolosite, le poți păstra în variabile Predicate și le poți combina cu and, or, negate.

Parametri

Parametru Descriere
conditie Funcția care primește un element și returnează true dacă elementul rămâne.

Ce returnează

Un nou stream doar cu elementele care au trecut condiția.

Exemple

Exemplul 1: Notele de trecere

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> note = List.of(9, 4, 7, 10, 3, 5, 8);
        List<Integer> trecute = note.stream()
                .filter(n -> n >= 5)
                .toList();
        System.out.println("Promovate: " + trecute);
    }
}

Rezultat

Promovate: [9, 7, 10, 5, 8]

Exemplul 2: Filtrarea obiectelor după mai multe câmpuri

Un record descrie un produs; păstrăm produsele din stoc mai ieftine de 50 de lei.

import java.util.List;

public class Main {
    record Produs(String nume, double pret, boolean inStoc) {}

    public static void main(String[] args) {
        List<Produs> produse = List.of(
                new Produs("Caiet", 12.5, true),
                new Produs("Rucsac", 149.9, true),
                new Produs("Pix", 4.0, false),
                new Produs("Penar", 35.0, true));

        produse.stream()
                .filter(Produs::inStoc)
                .filter(p -> p.pret() < 50)
                .forEach(p -> System.out.println(p.nume() + " – " + p.pret() + " lei"));
    }
}

Rezultat

Caiet – 12.5 lei
Penar – 35.0 lei

Exemplul 3: Condiții refolosite cu Predicate

import java.util.List;
import java.util.function.Predicate;

public class Main {
    public static void main(String[] args) {
        List<String> orase = List.of("Iași", "Ilfov", "Cluj", "Ploiești", "Iasi");
        Predicate<String> cuI = s -> s.startsWith("I");
        Predicate<String> cuDiacritice = s -> s.matches(".*[ăâîșț].*");

        System.out.println(orase.stream().filter(cuI).toList());
        System.out.println(orase.stream().filter(cuI.and(cuDiacritice)).toList());
        System.out.println(orase.stream().filter(cuI.negate()).toList());
    }
}

Rezultat

[Iași, Ilfov, Iasi]
[Iași]
[Cluj, Ploiești]

Greșeli frecvente

  • Inversezi sensul condiției: filter păstrează elementele pentru care condiția este adevărată, nu le elimină.
  • Apelezi filter și ignori rezultatul (lista.stream().filter(...);). Stream-ul nou nu modifică lista; ai nevoie de o operație finală, de exemplu toList().

Comenzi înrudite

  • Stream.map: Transformă fiecare element al stream-ului în altă valoare, eventual de alt tip.
  • Predicate: O condiție: primește o valoare și răspunde true sau false prin metoda test; folosită de filter, removeIf, anyMatch.
  • Predicate.and: Combină condiții: and (ambele adevărate), or (cel puțin una) și negate (condiția inversă).
  • Stream.takeWhile: takeWhile ia elemente cât timp condiția e adevărată și se oprește la primul care nu o respectă; dropWhile le sare pe acestea.
  • Stream.anyMatch: Verifică dacă cel puțin un element (anyMatch), toate (allMatch) sau niciunul (noneMatch) nu îndeplinesc o condiție.
  • Stream.count: Returnează numărul de elemente din stream, de tip long.