Как отфильтровать список
Короткий ответ
filter() оставляет в потоке только элементы, для которых условие истинно:
void main() {
var numbers = List.of(5, 12, 8, 21, 3);
var big = numbers.stream().filter(n -> n > 7).toList();
IO.println(big);
}Результат:
[12, 8, 21]По полю объекта
В условии обращайтесь к полям через методы доступа:
record Product(String name, double price, boolean inStock) {}
void main() {
var products = List.of(
new Product("Tea", 3.5, true),
new Product("Cake", 12.0, false),
new Product("Coffee", 7.9, true));
var available = products.stream().filter(Product::inStock).map(Product::name).toList();
IO.println(available);
}Результат:
[Tea, Coffee]Несколько условий
Объедините условия через && или вызовите filter() несколько раз:
void main() {
var words = List.of("apple", "Avocado", "banana", "apricot", "a");
var result = words.stream()
.filter(w -> w.length() > 1)
.filter(w -> w.toLowerCase().startsWith("a"))
.toList();
IO.println(result);
}Результат:
[apple, Avocado, apricot]Изменить сам список
Поток создаёт новый список. Чтобы удалить элементы из существующего, используйте removeIf() с обратным условием:
void main() {
var numbers = new ArrayList<>(List.of(5, 12, 8, 21, 3));
numbers.removeIf(n -> n <= 7);
IO.println(numbers);
}Результат:
[12, 8, 21]Частая ошибка
Ждать, что filter() изменит исходный список. Поток ничего не меняет, а без завершающей операции вроде toList() фильтр даже не выполняется:
void main() {
var numbers = List.of(5, 12, 8);
numbers.stream().filter(n -> n > 7);
IO.println(numbers);
}Результат:
[5, 12, 8]Функции из этого ответа
- Stream.filter() — Оставляет в потоке только элементы, подходящие под условие.
- Stream.toList() — Собирает элементы потока в неизменяемый список.
- Collection.removeIf() — Удаляет из коллекции все элементы, подходящие под условие.
- Predicate — Условие: функция, которая принимает значение и возвращает `boolean`.