Collectors.partitioningBy可按及格线(如60分)将学生分为及格与不及格两组,结合counting()统计人数并计算及格率,支持空集合防护、灵活阈值及后续数据处理。

用 Collectors.partitioningBy 统计学生及格率,核心是把学生列表按“是否及格”一分为二,再分别计算人数和比例,简洁又语义清晰。
明确分区条件:定义及格线
及格与否取决于成绩阈值,通常为60分。分区谓词应返回 Boolean,例如:
-
student -> student.getScore() >= 60—— 返回true表示及格,false表示不及格 - 注意:确保
getScore()返回的是可比较的数值类型(如int或double),避免空指针或类型异常
执行分区并获取基础计数
调用 partitioningBy 后得到一个 Map<boolean list>></boolean>,从中可直接提取两类学生集合:
Map<boolean list>> partitioned = students.stream().collect(Collectors.partitioningBy(s -> s.getScore() >= 60));</boolean>List<student> passed = partitioned.get(true);</student>List<student> failed = partitioned.get(false);</student>- 及格率 =
(double) passed.size() / students.size()(需防除零,建议先判空)
一步到位:嵌套下游收集器算比率
若想在一次流操作中同时获得及格人数、总人数与及格率,可结合 Collectors.counting() 和自定义映射:
- 先分区并统计每组数量:
Map<boolean long> countMap = students.stream().collect(Collectors.partitioningBy(s -> s.getScore() >= 60, Collectors.counting()));</boolean> - 再计算:
long total = students.size(); long passedCount = countMap.getOrDefault(true, 0L); double passRate = total > 0 ? (double) passedCount / total : 0.0; - 这样避免重复遍历,也更符合函数式风格
增强实用性:封装为可复用方法
将逻辑抽成工具方法,支持灵活传入分数字段和及格线:
public static <t> double calculatePassRate(List<t> data, ToIntFunction<t> scoreExtractor, int passingScore) { ... }</t></t></t>- 内部仍用
partitioningBy+counting(),提升复用性与可测性 - 例如调用:
calculatePassRate(students, Student::getScore, 60)
不复杂但容易忽略细节:空集合处理、分数边界(如含小数)、以及是否需要保留原始学生对象用于后续分析——partitioningBy 天然保留数据结构,比单纯计数更有延展性。

















