Arrays.sort()是Java平台经二十年打磨的高效排序方案,基本类型用双轴快排(含插入排序兜底、五取样选轴、三向切分、递归降级),对象数组用稳定TimSort(识别自然有序段、二分插入、归并合并),需避免装箱、越界、重逻辑Comparator等误用,并在值域有限、动态有序、Top-K等场景改用更优算法。

Arrays.sort()不是“你要去优化”的对象,而是Java平台已经替你完成二十年工程打磨的排序方案。它快,不是因为玄学,而是靠分层策略、阈值切换和场景适配——理解它怎么选算法,比手写快排重要得多。
基本类型用双轴快排:两个基准值,三段划分
对int[]、long[]、double[]等,JDK7起默认采用双轴快速排序(Dual-Pivot Quicksort)。它不选一个pivot,而是选两个(pivot1
– 左段:所有元素
– 中段:pivot1 ≤ 元素 ≤ pivot2
– 右段:所有元素 > pivot2
这种结构天然减少递归深度,也降低比较次数。比如对百万随机整数,实测比单轴快排快2–3倍。
关键细节包括:
- 长度小于47时,直接切到插入排序——小数组常数因子更优
- 选轴用“五取样法”:取首、中、尾及中间两点共5个元素,取中位数确定两个pivot,避免退化
- 重复元素多时启用三向切分,把等于pivot1/pivot2的元素集中归入中段,避免反复交换
- 递归过深(超过2×log₂n)时自动降级为归并排序,兜底防止O(n²)最坏情况
对象数组走TimSort:识别天然有序段,合并更聪明
String[]、Person[]、Integer[]这类对象数组,Arrays.sort()调用的是TimSort——Python也用它,是现实数据中最稳最快的混合算法。它不假设数据杂乱,而是先扫描找“自然有序片段”(Run),比如一段升序子数组或严格降序后反转的片段,再把这些Run当成基础单元,用二分插入补短、用归并合并长段。
这意味着:
立即学习“Java免费学习笔记(深入)”;
- 已基本排好序的数组(如日志按时间追加写入),TimSort接近O(n),几乎只扫一遍
- 含大量重复值或局部有序的数据,性能远超传统快排
- 它是稳定排序:相同元素相对位置不变,适合业务敏感场景(如按创建时间+ID二次排序)
- 空间开销略高(O(n)临时数组),但换来的是可预测的O(n log n)最坏表现
别踩这些常见性能坑
真正拖慢百万级排序的,往往不是算法本身,而是误用方式:
- 对int[]硬传Comparator:编译失败;真要降序,别装箱成Integer[]再排——百万int装箱会触发频繁GC,耗时翻倍
- 用Arrays.sort(arr, from, to)时记错右边界:to是“不包含”的索引,写成arr.length容易越界或漏排
- 自定义Comparator里做重操作:比如在compare里解析JSON、调用正则、new对象——每个比较都执行,放大N倍开销
- 明明是0–100万范围的用户ID,却用快排:改用计数排序,O(n)搞定,内存更省、速度更快
什么时候该换算法?
Arrays.sort很强大,但不是万能解:
- 纯整数且值域有限 → 计数排序或基数排序,实测快4–5倍
- 只要随机顺序(抽奖、测试数据)→ Collections.shuffle()(Fisher-Yates),别用Math.random()配sort
- 数据持续写入、需动态维护有序 → 数组不合适,换成TreeSet或ConcurrentSkipListSet
- 只取Top-K(比如前100名)→ 用PriorityQueue建大小为K的堆,O(n log k),比全量O(n log n)划算得多



















