




Collections.sort()排序需Student实现Comparable或传Comparator,推荐匿名Comparator;用Double.compare()防精度问题和溢出;null值用nullsLast()处理;Stream.sorted()适合不可变排序;并列名次需遍历打标。
Collections.sort() 对学生成绩列表排序直接对 List 排序最常用,前提是 Student 实现 Comparable 或传入 Comparator。别直接改 Student 类去实现 Comparable——万一以后要按姓名、学号、年龄多维度排序,硬编码比较逻辑会失控。
推荐写匿名 Comparator 或方法引用:
Collections.sort(students, (a, b) -> Double.compare(b.getScore(), a.getScore()));
注意:这里用 Double.compare() 而不是 a.getScore() - b.getScore(),避免浮点数减法导致的精度问题或整数溢出(比如分数是 int 但值超出了 Integer.MAX_VALUE - Integer.MIN_VALUE 范围)。
b 和 a 位置换过来thenComparing(Student::getName)
students 是 null 或含 null 元素,sort() 会抛 NullPointerException,得提前过滤或用 Comparator.nullsLast()
Stream.sorted() 做不可变排名想保留原始列表不变、只生成新排名列表?Stream 是更安全的选择。它天然支持链式操作,也更容易嵌入过滤、映射等逻辑。
示例:取前10名且分数 ≥ 60 的学生
Listtop10 = students.stream() .filter(s -> s.getScore() >= 60) .sorted((a, b) -> Double.compare(b.getScore(), a.getScore())) .limit(10) .collect(Collectors.toList());
注意:sorted() 是中间操作,必须接终端操作(如 collect、forEach)才会触发;没写 collect 就以为排好序了,结果是空的 Stream,容易误判。
sorted() 底层仍调用 Arrays.sort(),性能和 Collections.sort() 接近,不是懒加载
Stream 默认串行,不加 parallel() 不会自动并行,别指望它“自动加速”method reference 写排序器更简洁:sorted(Com
parator.comparingDouble(Student::getScore).reversed())
真实成绩单里“95、95、92”应该显示为“1、1、3”,而不是“1、2、3”。Java 集合排序本身不提供这种名次计算,得自己遍历打标。
关键点:不能只依赖排序后索引(i + 1),必须比对相邻分数是否相等:
int rank = 1;
for (int i = 0; i < rankedStudents.size(); i++) {
Student s = rankedStudents.get(i);
if (i > 0 && Double.compare(s.getScore(), rankedStudents.get(i-1).getScore()) == 0) {
s.setRank(rank); // 分数相同,名次不变
} else {
rank = i + 1;
s.setRank(rank);
}
}这里用 Double.compare() 判断相等,而非 ==,防止浮点误差;如果分数字段是 BigDecimal,就得用 compareTo()。
sort() 里试图塞进名次逻辑——排序器只能返回 -1/0/1,没法传状态rank = i + 1 改成 rank++ 即可null 时排序崩溃怎么办NullPointerException 是最常踩的坑。哪怕数据库字段允许为空,Java 对象里 score 是 Double(包装类)就可能为 null,而 Double.compare(null, x) 直接炸。
安全做法是显式处理 null:用 Comparator.nullsLast() 或 nullsFirst() 包一层
ComparatorbyScore = Comparator.comparing( Student::getScore, Comparator.nullsLast(Comparator.reverseOrder()) );
这样 null 成绩会被排在最后(降序时),且不会抛异常。如果业务要求 null 当作 0 处理,就该在 getScore() 里返回 Objects.requireNonNullElse(score, 0.0),而不是在排序器里硬转——职责要分明。
compareTo(比如 Lombok 的 @Data),它对 null 字段默认抛异常null 值,有时会变成 0.0 或空字符串,取决于类型处理器,务必实测score = null 场景,否则上线后第一份零分名单就崩排名功能看着简单,真正落地时 null 值、浮点精度、并列规则、原始数据不可变这几个点,漏掉任何一个都可能让导出的 Excel 名次列对不上。