Java 8引入的Stream流API提供了丰富的集合操作工具,其中Collectors.partitioningBy是专门用于根据谓词条件对集合元素进行分区的收集器,它可以将集合拆分为两个子集合,分别对应条件成立和条件不成立的元素组。

Collectors.partitioningBy基础用法
Collectors.partitioningBy的核心作用是接收一个Predicate谓词作为参数,对Stream中的元素进行判断,最终返回一个Map<Boolean, List<T>>结构的映射,键为true的集合存放满足条件的元素,键为false的集合存放不满足条件的元素。
下面是一个简单的示例,将整数集合分为偶数和奇数两组:
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class PartitioningByDemo {
public static void main(String[] args) {
// 创建一个整数集合
List<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.collect(Collectors.toList());
// 使用partitioningBy分区,判断条件为是否为偶数
Map<Boolean, List<Integer>> partitionResult = numbers.stream()
.collect(Collectors.partitioningBy(num -> num % 2 == 0));
// 输出偶数集合
System.out.println("偶数集合:" + partitionResult.get(true));
// 输出奇数集合
System.out.println("奇数集合:" + partitionResult.get(false));
}
}
运行上述代码后,输出结果如下:
偶数集合:[2, 4, 6, 8, 10]
奇数集合:[1, 3, 5, 7, 9]
带下游收集器的partitioningBy用法
Collectors.partitioningBy还有一个重载方法,除了接收谓词参数外,还可以接收一个下游收集器,用于对分区后的每个子集合做进一步的处理,比如统计数量、求和、转换元素等。
下面的示例先按学生是否及格分区,再统计每个分区的学生数量:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Student {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public int getScore() {
return score;
}
@Override
public String toString() {
return name + "(分数:" + score + ")";
}
}
public class PartitioningByWithDownstream {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("张三", 85),
new Student("李四", 59),
new Student("王五", 92),
new Student("赵六", 48),
new Student("孙七", 76)
);
// 先按是否及格(分数>=60)分区,再统计每个分区的数量
Map<Boolean, Long> countByPass = students.stream()
.collect(Collectors.partitioningBy(
student -> student.getScore() >= 60,
Collectors.counting()
));
System.out.println("及格人数:" + countByPass.get(true));
System.out.println("不及格人数:" + countByPass.get(false));
// 先分区,再收集每个分区的学生姓名
Map<Boolean, List<String>> nameByPass = students.stream()
.collect(Collectors.partitioningBy(
student -> student.getScore() >= 60,
Collectors.mapping(Student::toString, Collectors.toList())
));
System.out.println("及格学生:" + nameByPass.get(true));
System.out.println("不及格学生:" + nameByPass.get(false));
}
}
运行结果如下:
及格人数:3
不及格人数:2
及格学生:[张三(分数:85), 王五(分数:92), 孙七(分数:76)]
不及格学生:[李四(分数:59), 赵六(分数:48)]
partitioningBy和groupingBy的区别
很多开发者会混淆Collectors.partitioningBy和Collectors.groupingBy,两者的核心区别如下:
partitioningBy的分区条件只能是Predicate谓词,结果固定分为两组,键的类型是Boolean。groupingBy的分组条件可以是任意的Function函数,分组数量不固定,键的类型由分组函数的返回值决定。
如果只需要将集合分为满足和不满足条件两组,优先使用partitioningBy,语义更清晰,性能也略好;如果需要按多个类别分组,则使用groupingBy。
使用注意事项
使用Collectors.partitioningBy时需要注意以下几点:
- 如果分区后某个键对应的集合没有元素,返回的
Map中仍然会包含该键,对应的值为空集合,不会返回null,因此不需要做空值判断。 - 下游收集器可以嵌套使用,比如先分区,再对每个分区的元素做分组、统计等操作,满足复杂的数据处理需求。
- 该方法只能用于Stream流的
collect终端操作,不能单独使用。
Collectors_partitioningByJava集合分区Stream流集合分组Lambda表达式修改时间:2026-07-17 15:06:32