Collections.sort 是稳定排序,其底层调用 Arrays.sort(Object[]) 使用稳定的 TimSort 算法,确保相等元素相对顺序不变;而 Arrays.sort(int[]) 等基本类型重载版本使用不稳定的双轴快排,但 Collections.sort 永不调用这些版本。

Collections.sort 是稳定排序,原生基本类型数组排序(如 Arrays.sort(int[]))不稳定,但二者不直接可比——因为 Collections.sort 从不处理基本类型数组。
什么是“稳定性”?
稳定性指:当多个元素被判定为“相等”(即比较器返回 0)时,它们在排序后的相对顺序与原始列表中一致。比如两个 Person 对象年龄相同,排序后原来排在前面的那个仍靠前。
这和“值重复”无关,而取决于你写的 Comparator 或 compareTo() 如何定义“相等”。Java 不关心业务逻辑上的“重复”,只看比较结果是否为 0。
Collections.sort 的稳定性有保障
它底层调用 Arrays.sort(Object[]),对引用类型始终使用 TimSort 算法——这是明确设计为稳定的归并排序变种。
- 只要 List 是 ArrayList、Vector 或其他支持随机访问的实现,排序过程就稳定
- 即使传入 LinkedList,Collections.sort 也会先转成数组排序,再写回链表,稳定性仍保留
- 自定义 Comparator 中若把不同对象判为相等(例如只比 name,忽略 id),它们的原始先后关系会被完整保留
别混淆:Arrays.sort 的重载行为不同
很多人误以为“Arrays.sort 不稳定,所以 Collections.sort 也不稳”,这是错的——因为 Collections.sort 根本不会触发 Arrays.sort 的基本类型重载版本。
-
Arrays.sort(int[])→ 双轴快排 → 不稳定(但 Collections.sort 永远不调用它) -
Arrays.sort(String[])或Arrays.sort(Person[])→ TimSort → 稳定 - Collections.sort(list) 内部走的是
Arrays.sort(Object[], Comparator)路径,永远落在稳定分支
看起来“不稳定”的常见原因
不是算法失灵,而是代码或数据出了问题:
- Comparator 里用了
a - b做整数比较,导致溢出后返回错误符号,让本不该相等的数被判相等(或相反) - 字段可能为 null 却没用
Comparator.nullsLast(),抛出异常中断排序,列表处于中间状态 - 排序时另一线程正在修改列表,或者用了 CopyOnWriteArrayList 这类“快照式”集合,看到的数据不是你预期的
- 误把不可修改列表(如 Arrays.asList 返回值被包装成 unmodifiable)传进去,排序失败而非行为异常

















