Collectors.partitioningBy根据布尔条件将流元素分为两组,适用于二元分类场景。例如按年龄区分成年与未成年用户,支持结合下游收集器统计数量或提取属性,提升代码可读性。

在Java 8引入的Stream API中,Collectors.partitioningBy 是一个非常实用的收集器,它可以根据一个布尔条件将集合元素划分为两个分区:满足条件的归为一组(key为true),不满足的归为另一组(key为false)。这种操作在需要对数据进行二分分类时特别高效。
partitioningBy的基本用法
该方法接收一个Predicate函数式接口作为参数,返回一个Map<Boolean, List<T>>类型的结果。下面是一个简单的例子:
假设我们有一个用户列表,想把成年用户和未成年用户分开:
List<User> users = Arrays.asList(
new User("Alice", 25),
new User("Bob", 17),
new User("Charlie", 30),
new User("Diana", 16)
);
Map<Boolean, List<User>> partitionedByAge = users.stream()
.collect(Collectors.partitioningBy(user -> user.getAge() >= 18));
System.out.println("成年人: " + partitionedByAge.get(true));
System.out.println("未成年人: " + partitionedByAge.get(false));
输出结果将是:
立即学习“Java免费学习笔记(深入)”;
成年人: [User{name='Alice', age=25}, User{name='Charlie', age=30}]
未成年人: [User{name='Bob', age=17}, User{name='Diana', age=16}]
结合下游收集器进行高级分区
除了默认生成List外,还可以指定下游收集器来改变分区后的数据结构。例如,只统计每组人数:
Map<Boolean, Long> countByAgeGroup = users.stream()
.collect(Collectors.partitioningBy(
user -> user.getAge() >= 18,
Collectors.counting()
));
System.out.println("成年组人数: " + countByAgeGroup.get(true)); // 输出 2
System.out.println("未成年组人数: " + countByAgeGroup.get(false)); // 输出 2
也可以将名字提取成集合:
Map<Boolean, List<String>> namesPartitioned = users.stream()
.collect(Collectors.partitioningBy(
user -> user.getAge() >= 18,
Collectors.mapping(User::getName, Collectors.toList())
));
实际应用场景建议
使用 partitioningBy 适合处理非此即彼的二元分类问题。比如:
- 区分通过/未通过考试的学生
- 分离启用或禁用状态的配置项
- 按奇偶数拆分数字列表
- 判断字符串是否为空或符合格式
注意:如果分类标准多于两种,应考虑使用 Collectors.groupingBy 而不是多次调用partitioningBy。
基本上就这些。合理利用partitioningBy能让代码更清晰,减少手动遍历和if-else判断,提升可读性和维护性。










