Collectors là phần thiết yếu của Stream API. Java 9 thêm filtering() vào Collectors. Dùng để lọc element trong stream – tương tự filter() trên stream nhưng filtering() kết hợp tốt với Collectors.groupingBy(): group trước, lọc sau.
Cú pháp
public static <T, A, R> Collector<T, ?, R> filtering(
Predicate<? super T> predicate,
Collector<? super T, A, R> downstream)
Ví dụ: Group by length, lọc bỏ string chứa 'z'
import java.util.stream.*;
import java.util.*;
public class FilteringMethodTest {
public static void main(String args[]) {
List<String> list = List.of("x", "yy", "zz", "www");
Map<Integer, List<String>> result = list.stream()
.collect(Collectors.groupingBy(
String::length,
Collectors.filtering(s -> !s.contains("z"), Collectors.toList())
));
System.out.println(result);
}
}
Kết quả
{1=[x], 2=[yy], 3=[www]}
Giải thích
- Input: ["x"(len1), "yy"(len2), "zz"(len2), "www"(len3)].
- Group by length: {1:["x"], 2:["yy","zz"], 3:["www"]}.
filtering(s -> !s.contains("z"), toList()): Trong mỗi group, lọc bỏ string có 'z'.- Group 2: ["yy","zz"] → lọc → ["yy"].
- Kết quả: {1=["x"], 2=["yy"], 3=["www"]}.
filter() vs filtering()
| Đặc điểm | stream.filter() | Collectors.filtering() |
|---|---|---|
| Thời điểm lọc | Trước khi collect/group | Sau khi group (trong downstream collector) |
| Kết hợp groupingBy | Lọc toàn bộ stream trước group | Lọc riêng từng group |
| Use case | Lọc global | Lọc conditional per group |
Ví dụ so sánh
// stream.filter() - lọc trước khi group
list.stream()
.filter(s -> !s.contains("z"))
.collect(groupingBy(String::length));
// Kết quả: {1=[x], 2=[yy], 3=[www]} (zz bị loại hoàn toàn)
// Collectors.filtering() - lọc trong group
list.stream()
.collect(groupingBy(String::length, filtering(s -> !s.contains("z"), toList())));
// Kết quả: {1=[x], 2=[yy], 3=[www]} (zz bị loại trong group 2, nhưng group 2 vẫn tồn tại với yy)
Collectors.filtering() cho phép logic lọc phức tạp per-group trong collector pipeline.