Что делает метод filter в Stream?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что делает метод 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.