How to filter a list
Short answer
filter() keeps only the elements for which the condition is true:
void main() {
var numbers = List.of(5, 12, 8, 21, 3);
var big = numbers.stream().filter(n -> n > 7).toList();
IO.println(big);
}Output:
[12, 8, 21]By an object field
Access the fields through accessor methods in the condition:
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);
}Output:
[Tea, Coffee]Several conditions
Combine conditions with && or call filter() several times:
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);
}Output:
[apple, Avocado, apricot]Changing the list itself
A stream creates a new list. To remove elements from an existing list, use removeIf() with the opposite condition:
void main() {
var numbers = new ArrayList<>(List.of(5, 12, 8, 21, 3));
numbers.removeIf(n -> n <= 7);
IO.println(numbers);
}Output:
[12, 8, 21]Common mistake
Expecting filter() to change the original list. A stream changes nothing, and without a terminal operation like toList() the filter does not even run:
void main() {
var numbers = List.of(5, 12, 8);
numbers.stream().filter(n -> n > 7);
IO.println(numbers);
}Output:
[5, 12, 8]Functions used in this recipe
- Stream.filter() — Keeps only the stream elements that match a condition.
- Stream.toList() — Gathers stream elements into an unmodifiable list.
- Collection.removeIf() — Removes all collection elements that match a condition.
- Predicate — A condition: a function that takes a value and returns a `boolean`.