filter
TL;DR
filter(Predicate<T>)is an intermediate stream operation.- It is used to conditionally include or exclude elements from the stream.
- Only elements for which the provided Predicate returns
trueare passed to the next step in the pipeline.
Concept
The filter operation is the functional equivalent of an if statement inside a for loop.
It takes a Predicate (a function returning a boolean). It evaluates every element in the stream against this predicate.
- If
true, the element continues down the stream. - If
false, the element is dropped and ignored.
Because filter is an intermediate operation, it is executed lazily and returns a new stream containing only the filtered elements.
Examples
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class FilterExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 1. Simple Filter: Get only even numbers
List<Integer> evens = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println("Evens: " + evens); // [2, 4, 6, 8, 10]
// 2. Multiple Filters
// It is often more readable to chain multiple small filters
// than to write one massive, complex condition.
List<Integer> specificNumbers = numbers.stream()
.filter(n -> n > 5) // Keep 6, 7, 8, 9, 10
.filter(n -> n % 2 != 0) // Keep 7, 9
.collect(Collectors.toList());
System.out.println("Specific: " + specificNumbers); // [7, 9]
}
}
Interview Questions
Q: Is it better to chain multiple filter() calls or use one filter() with logical ANDs (&&)?
A: From a performance perspective, there is virtually no difference because the JVM optimizes the pipeline. However, from a readability and maintainability perspective, chaining multiple .filter() calls is usually preferred. It allows you to easily comment out specific rules during debugging, or pass in predefined Predicate variables for cleaner code.
Q: Can filter() change the type of objects in the stream?
A: No. filter operates on Stream<T> and returns Stream<T>. It can only reduce the count of elements, it cannot transform them. To change the type of the objects, you must use the map() operation.