在Java 8引入的Stream API中,Collectors.partitioningBy()是专门用于实现二元分组的核心收集器,它可以根据指定的断言函数(Predicate)将流中的元素划分为两个组:满足条件的一组和不满足条件的一组,非常适合用来处理考试成绩按及格和不及格分类的场景。

Collectors.partitioningBy() 核心原理
Collectors.partitioningBy()有两个常用的重载方法,第一个只接收一个Predicate参数,第二个除了接收Predicate参数外,还可以接收一个下游收集器用来对分组后的数据进行二次处理。
它的返回值是一个Map<Boolean, D>结构,其中键是Boolean类型,true对应满足谓词条件的元素集合,false对应不满足谓词条件的元素集合,这正好契合及格和不及格的二元分类需求。
基础方法定义
// 仅按谓词分组,值为元素列表
public static <T>
Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate)
// 按谓词分组后,对每组元素用下游收集器处理
public static <T, D, A>
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
Collector<? super T, A, D> downstream)
考试成绩分类实现步骤
我们以存储学生姓名和考试成绩的实体类为基础,演示完整的分类实现过程。
1. 定义成绩实体类
首先创建存储成绩数据的实体类,包含学生姓名和分数两个属性。
class ExamScore {
private String studentName;
private int score;
public ExamScore(String studentName, int score) {
this.studentName = studentName;
this.score = score;
}
public String getStudentName() {
return studentName;
}
public int getScore() {
return score;
}
@Override
public String toString() {
return studentName + ":" + score;
}
}
2. 准备测试成绩数据
构建一个包含多个学生成绩的集合,作为后续分组的数据源。
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ScorePartitionDemo {
public static void main(String[] args) {
// 准备成绩数据
List<ExamScore> scoreList = new ArrayList<>();
scoreList.add(new ExamScore("张三", 85));
scoreList.add(new ExamScore("李四", 59));
scoreList.add(new ExamScore("王五", 92));
scoreList.add(new ExamScore("赵六", 48));
scoreList.add(new ExamScore("孙七", 73));
scoreList.add(new ExamScore("周八", 60));
}
}
3. 使用 partitioningBy 实现二元分类
设定及格线为60分,将分数大于等于60分的归为及格组,小于60分的归为不及格组。
// 按60分及格线分组,true为及格,false为不及格
Map<Boolean, List<ExamScore>> scorePartition = scoreList.stream()
.collect(Collectors.partitioningBy(score -> score.getScore() >= 60));
// 获取及格的成绩列表
List<ExamScore> passedList = scorePartition.get(true);
// 获取不及格的成绩列表
List<ExamScore> failedList = scorePartition.get(false);
System.out.println("及格学生列表:");
passedList.forEach(System.out::println);
System.out.println("不及格学生列表:");
failedList.forEach(System.out::println);
运行上述代码后,输出结果如下:
及格学生列表: 张三:85 王五:92 孙七:73 周八:60 不及格学生列表: 李四:59 赵六:48
进阶:对分组结果做二次统计
如果需要统计及格和不及格的人数,或者计算两组的平均分,可以使用带下游收集器的partitioningBy重载方法。
统计每组人数
// 统计及格和不及格的人数
Map<Boolean, Long> countPartition = scoreList.stream()
.collect(Collectors.partitioningBy(
score -> score.getScore() >= 60,
Collectors.counting()
));
System.out.println("及格人数:" + countPartition.get(true));
System.out.println("不及格人数:" + countPartition.get(false));
计算每组平均分
// 计算及格和不及格组的平均分
Map<Boolean, Double> avgScorePartition = scoreList.stream()
.collect(Collectors.partitioningBy(
score -> score.getScore() >= 60,
Collectors.averagingInt(ExamScore::getScore)
));
System.out.println("及格组平均分:" + avgScorePartition.get(true));
System.out.println("不及格组平均分:" + avgScorePartition.get(false));
注意事项
- 谓词条件的边界需要明确,比如上述例子中60分算及格,所以条件用
score.getScore() >= 60,如果需求是60分及以上算及格,不要写成> 60。 - 当流中没有元素满足谓词条件时,
Map中仍然会有true和false两个键,对应的值会是下游收集器的默认值,比如用toList()时就是空列表,用counting()时就是0。 - 如果需要分组后返回不可修改的集合,可以在下游收集器中使用
Collectors.collectingAndThen()做一层包装,避免后续误操作修改分组结果。
Collectors_partitioningByJava_stream成绩分类二元分组修改时间:2026-06-22 01:03:26