← Назад к вопросам

Что делает метод filter в Stream?

1.0 Junior🔥 191 комментариев
#Stream API и функциональное программирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что делает метод filter в Stream?

Метод filter() в Stream API Java — это промежуточная операция, которая фильтрует элементы потока, оставляя только те, которые соответствуют определённому условию (предикату). Это один из самых полезных и часто используемых методов при работе с потоками данных.

Сигнатура метода

Stream<T> filter(Predicate<? super T> predicate)

Метод принимает Predicate — функциональный интерфейс, который возвращает boolean. Если условие истинно, элемент попадает в новый поток, если нет — отфильтровывается.

Основное поведение

  • Промежуточная операция — не терминальная, может быть вызвана цепочкой других операций
  • Ленивая вычисления — работает только когда вызвана терминальная операция
  • Неменяющая — исходный поток не изменяется, создаётся новый

Простой пример

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Фильтруем только чётные числа
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)  // Predicate: (n % 2 == 0)
    .collect(Collectors.toList());

System.out.println(evenNumbers); // [2, 4, 6, 8, 10]

Фильтрация объектов

class Person {
    String name;
    int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

List<Person> people = Arrays.asList(
    new Person("Alice", 25),
    new Person("Bob", 17),
    new Person("Charlie", 30),
    new Person("Diana", 16)
);

// Фильтруем людей старше 18 лет
List<Person> adults = people.stream()
    .filter(p -> p.age >= 18)
    .collect(Collectors.toList());

// Результат: Alice (25), Charlie (30)

Множественные фильтры (цепочка)

Можно применить несколько filter() подряд:

List<Integer> result = numbers.stream()
    .filter(n -> n > 5)        // Больше 5
    .filter(n -> n % 2 == 0)   // И чётные
    .collect(Collectors.toList());

// Результат: [6, 8, 10]

Это эквивалентно:

List<Integer> result = numbers.stream()
    .filter(n -> n > 5 && n % 2 == 0)
    .collect(Collectors.toList());

Работа с null значениями

List<String> words = Arrays.asList("hello", null, "world", null, "java");

// Убираем null значения
List<String> nonNull = words.stream()
    .filter(Objects::nonNull)  // Objects.nonNull(obj)
    .collect(Collectors.toList());

// Результат: [hello, world, java]

Сложный пример с фильтрацией строк

List<String> words = Arrays.asList(
    "apple", "banana", "apricot", "cherry", "avocado"
);

// Слова, начинающиеся на 'a' и длиной более 4 символов
List<String> filtered = words.stream()
    .filter(w -> w.startsWith("a"))
    .filter(w -> w.length() > 4)
    .collect(Collectors.toList());

// Результат: [apple, apricot, avocado]

Производительность: ленивые вычисления

Фильтр работает лениво — вычисления происходят только при вызове терминальной операции:

Stream<Integer> stream = numbers.stream()
    .filter(n -> {
        System.out.println("Checking: " + n);
        return n > 5;
    });

// Здесь ничего не печатается! filter() не выполнен

stream.collect(Collectors.toList()); // Теперь выполняется

Терминальные операции после filter()

// collect() — собрать в список
List<Integer> list = stream.filter(...).collect(Collectors.toList());

// forEach() — выполнить действие для каждого
stream.filter(...).forEach(System.out::println);

// count() — подсчитать элементы
long count = stream.filter(...).count();

// findFirst() — найти первый
Optional<Integer> first = stream.filter(...).findFirst();

// reduce() — свернуть в одно значение
Optional<Integer> sum = stream.filter(...).reduce(Integer::sum);

Отличие от цикла

Традиционный цикл:

List<Integer> result = new ArrayList<>();
for (Integer n : numbers) {
    if (n > 5 && n % 2 == 0) {
        result.add(n);
    }
}

Stream с filter():

List<Integer> result = numbers.stream()
    .filter(n -> n > 5 && n % 2 == 0)
    .collect(Collectors.toList());

Stream версия более декларативная, читаемая и позволяет использовать параллельные потоки.

Вывод: filter() — это универсальный инструмент для отсеивания элементов потока по заданному условию, оставляя только нужные. Это основной строительный блок функциональной обработки данных в Java.