Что делает метод filter() в Java Stream API?

«Что делает метод filter() в Java Stream API?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Метод filter(Predicate<? super T> predicate) — это промежуточная операция в Stream API, которая отфильтровывает элементы, не соответствующие заданному условию. Он возвращает новый поток, содержащий только элементы, для которых предикат вернул true.

Синтаксис и параметры:

  • Предикат (Predicate<T>): Функциональный интерфейс, метод test(T t) которого возвращает boolean.
  • Возвращаемое значение: Stream<T> — новый поток отфильтрованных элементов.

Примеры:

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

// Фильтрация чётных чисел
List<Integer> evens = numbers.stream()
        .filter(n -> n % 2 == 0) // Предикат: true для чётных
        .collect(Collectors.toList()); // [2, 4, 6]

// Цепочка операций: фильтрация + преобразование
List<String> result = numbers.stream()
        .filter(n -> n > 3)          // [4, 5, 6]
        .map(n -> "#" + n)           // ["#4", "#5", "#6"]
        .collect(Collectors.toList());

Ключевые свойства:

  • Ленивый: Фильтрация не происходит до вызова терминальной операции (например, collect).
  • Не изменяет источник: Исходная коллекция остаётся неизменной.
  • Может быть stateless или stateful: Обычно используется простой stateless-предикат. Для сложной логики можно вынести предикат в отдельный метод.

Почему это best practice: filter() позволяет декларативно и читаемо описывать критерии отбора данных, избегая императивных циклов и условных операторов внутри них.