Understanding Collectors.filtering()
in Java 9+ with Examples
Today we are going to learn new topic, lets learn with me.
Table of Contents
- Introduction
- Collectors.filtering() Method Syntax
- How Collectors.filtering() Works
- Examples
- Basic Usage
- Using filtering() with Multiple Conditions
5. Real-World Use Case
6. Alternative for Java 8
7. Conclusion
1. Introduction
Before Java 9, filtering elements inside a collector required extra filter()
operations before collecting results. However, Java 9 introduced Collectors.filtering()
, which allows filtering elements inside collectors like groupingBy()
or partitioningBy()
.
Why Use Collectors.filtering()
?
✅ Simplifies filtering inside collectors (e.g., groupingBy()
, partitioningBy()
).
✅ Keeps filtering logic inside the collector rather than adding extra filter()
before collect()
.
✅ More readable and concise for handling grouped data.
2. Collectors.filtering()
Method Syntax
static <T, A, R> Collector<T, ?, R> filtering(
Predicate<? super T> predicate, // Condition to filter elements
Collector<? super T, A, R> downstream // Collector to collect filtered elements
)
Parameters:
predicate
– The condition used to filter elements.downstream
– The collector that collects the filtered elements.
Returns:
A collector that filters elements based on the predicate before passing them to the downstream collector.
3. How Collectors.filtering()
Works
Imagine we have a list of numbers and we want to group them by even/odd while keeping only numbers greater than 5.
Before Java 9 (without Collectors.filtering()
):
Map<Boolean, List<Integer>> groupedNumbers = numbers.stream()
.filter(n -> n > 5) // Filtering before collecting
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
✅ Works, but filtering happens before collecting.
With Java 9+ (Collectors.filtering()
):
Map<Boolean, List<Integer>> groupedNumbers = numbers.stream()
.collect(Collectors.partitioningBy(
n -> n % 2 == 0,
Collectors.filtering(n -> n > 5, Collectors.toList())
));
✅ Filtering is inside partitioningBy()
, making it cleaner and more readable.
4. Examples
4.1 Basic Usage
Filtering Even/Odd Numbers Greater than 5
import java.util.*;
import java.util.stream.Collectors;
public class FilteringExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Map<Boolean, List<Integer>> partitionedNumbers = numbers.stream()
.collect(Collectors.partitioningBy(
n -> n % 2 == 0, // Group by even/odd
Collectors.filtering(n -> n > 5, Collectors.toList()) // Keep numbers > 5
));
System.out.println("Even numbers > 5: " + partitionedNumbers.get(true));
System.out.println("Odd numbers > 5: " + partitionedNumbers.get(false));
}
}
//------OUTPUT-----//
Even numbers > 5: [6, 8, 10]
Odd numbers > 5: [7, 9]
👉 Filtering happens within partitioningBy()
instead of using filter()
before collecting.
4.2 Using filtering()
with Multiple Conditions
Filtering Words That Start with first letter and Have More Than 5 Letters
import java.util.*;
import java.util.stream.Collectors;
public class FilteringMultipleConditions {
public static void main(String[] args) {
List<String> items = Arrays.asList("apple", "banana", "avocado", "grape", "apricot");
Map<Character, List<String>> groupedItems = items.stream()
.collect(Collectors.groupingBy(
word -> word.charAt(0), // Group by first letter
Collectors.filtering(word -> word.length() > 5, Collectors.toList()) // Keep words with > 5 chars
));
System.out.println(groupedItems);
}
}
//-------OUTPUT------//
{a=[avocado, apricot], b=[banana], g=[]}
👉 Efficiently filters words inside groupingBy()
rather than using multiple filters.
Explanation:-
Filtering Words That Start with “a ”and Have More Than 5 Letters using
import java.util.List;
import java.util.stream.Collectors;
public class FilteringExample {
public static void main(String[] args) {
List<String> words = List.of("apple", "apricot", "banana", "avocado", "artichoke", "almond", "grape");
List<String> result = words.stream()
.collect(Collectors.filtering(
word -> word.startsWith("a") && word.length() > 5, // Filtering condition
Collectors.toList() // Collect into List
));
System.out.println(result);
}
}
//-----OUTPUT----//
[apricot, avocado, artichoke, almond]
Using JAVA 8 :-
Since Collectors.filtering()
was introduced in Java 9, in Java 8, we can use filter()
inside the stream.
import java.util.List;
import java.util.stream.Collectors;
public class FilteringExampleJava8 {
public static void main(String[] args) {
List<String> words = List.of("apple", "apricot", "banana", "avocado", "artichoke", "almond", "grape");
List<String> result = words.stream()
.filter(word -> word.startsWith("a") && word.length() > 5) // Filtering condition
.collect(Collectors.toList()); // Collect into List
System.out.println(result);
}
}
//----OUTPUT--//
[apricot, avocado, artichoke, almond]
5. Real-World Use Case
Filtering Expensive Products by Category
Imagine an e-commerce system where we want to group products by category and keep only expensive ones (> $1000).
import java.util.*;
import java.util.stream.Collectors;
class Product {
String name;
String category;
double price;
Product(String name, String category, double price) {
this.name = name;
this.category = category;
this.price = price;
}
}
public class FilteringRealWorldExample {
public static void main(String[] args) {
List<Product> products = Arrays.asList(
new Product("iPhone", "Electronics", 1200),
new Product("Laptop", "Electronics", 1500),
new Product("Mouse", "Electronics", 50),
new Product("Table", "Furniture", 300),
new Product("Sofa", "Furniture", 1200)
);
Map<String, List<Product>> expensiveProducts = products.stream()
.collect(Collectors.groupingBy(
product -> product.category,
Collectors.filtering
(product -> product.price > 1000, Collectors.toList())
));
System.out.println(expensiveProducts);
}
}
//------OUTPUT-----//
{Electronics=[iPhone, Laptop], Furniture=[Sofa]}
👉 Filters expensive products while grouping them by category.
6. Alternative for Java 8
Since Java 8 does not support Collectors.filtering()
, you can use stream().filter()
before collecting:
Map<Boolean, List<Integer>> partitionedNumbers = new HashMap<>();
partitionedNumbers.put(true, numbers.stream()
.filter(n -> n % 2 == 0)
.filter(n -> n > 5)
.collect(Collectors.toList()));
partitionedNumbers.put(false, numbers.stream()
.filter(n -> n % 2 != 0)
.filter(n -> n > 5)
.collect(Collectors.toList()));
✅ Achieves the same result but requires multiple filters.
7. Conclusion
Collectors.filtering()
(Java 9) simplifies filtering inside collectors likegroupingBy()
andpartitioningBy()
.- Reduces the need for
filter()
before collecting, making the code cleaner and easier to read. - Java 8 alternative: Use
stream().filter()
beforecollect()
.
🚀 If you’re using Java 9+, Collectors.filtering()
is a great way to optimize your Stream API operations.
Happy Learning :)