Understanding Collectors.filtering() in Java 9+ with Examples

Today we are going to learn new topic, lets learn with me.

Table of Contents

  1. Introduction
  2. Collectors.filtering() Method Syntax
  3. How Collectors.filtering() Works
  4. 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 like groupingBy() and partitioningBy().
  • Reduces the need for filter() before collecting, making the code cleaner and easier to read.
  • Java 8 alternative: Use stream().filter() before collect().

🚀 If you’re using Java 9+, Collectors.filtering() is a great way to optimize your Stream API operations.

Happy Learning :)

--

--

No responses yet