In Java 9, the Collectors.filtering method was introduced to the Stream API as part of java.util.stream.Collectors. It allows you to apply a filter to elements of a stream before collecting them into a downstream collector (e.g., toList, toSet, etc.).
This can be particularly useful when you want to filter elements as part of the data collection pipeline.
Syntax
static <T, A, R> Collector<T, ?, R> filtering(Predicate<? super T> predicate, Collector<? super T, A, R> downstream)
predicate: A filter condition to be applied (e.g., a lambda expression).downstream: The collector that will gather the filtered elements (e.g.,Collectors.toList()).
How It Works
- The
filteringmethod applies the specifiedPredicateto filter the elements of the stream. - Only the elements that match the predicate are passed to the downstream collector.
- The filtered results are then collected as specified by the downstream collector.
Usage Example
Here’s a basic example of using Collectors.filtering:
Collecting only even integers from a list:
package org.kodejava.util.stream;
import java.util.List;
import java.util.stream.Collectors;
public class FilteringExample {
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Apply filtering before collecting to a list
List<Integer> evenNumbers = numbers.stream()
.collect(Collectors.filtering(n -> n % 2 == 0, Collectors.toList()));
System.out.println("Even Numbers: " + evenNumbers);
}
}
Output:
Even Numbers: [2, 4, 6, 8, 10]
Filtering with Downstream Grouping
You can use filtering in more complex collectors, such as those involving grouping. For example:
Grouping strings by their first character and filtering only strings longer than 3 characters:
package org.kodejava.util.stream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class FilteringWithGrouping {
public static void main(String[] args) {
List<String> words = List.of("apple", "ant", "banana", "bat", "cat", "car", "dog");
// Group by the first character and filter words with length > 3
Map<Character, List<String>> filteredWordsByGroup = words.stream()
.collect(Collectors.groupingBy(
word -> word.charAt(0), // Grouping by the first character
Collectors.filtering(
word -> word.length() > 3, // Filter words with length > 3
Collectors.toList() // Collect filtered words into a list
)
));
System.out.println("Filtered Words: " + filteredWordsByGroup);
}
}
Output:
Filtered Words: {a=[apple], b=[banana], c=[cat, car], d=[dog]}
When to Use
Collectors.filtering is particularly useful for:
- Grouped collections: Applying a filter while grouping elements.
- Custom collections: Collecting filtered elements into different collection types without needing an intermediate filtered stream.
- Improved readability: Reduces the need for chaining multiple
Stream.filter()calls in complex data processing.
Overall, Collectors.filtering makes streams more flexible and concise for advanced data collection scenarios!
