Arrays.sort是一套根据数组类型、长度和数据分布自动切换算法的排序策略:基本类型用双轴快排,对象类型及带Comparator的数组用TimSort;小数组(≤47)自动切插入排序,且不返回新数组、不保证基本类型稳定性。

Arrays.sort 不是“一个排序方法”,而是一套策略
它不硬编码某一种算法,而是根据数组类型、长度、数据分布自动切换底层实现。用错场景或误读行为,容易引发性能问题或逻辑错误。
基本类型用双轴快排,对象类型用 TimSort
这是最核心的区分点:
-
int[]、double[]、char[] 等基本类型数组:调用
Dual-Pivot Quicksort(双轴快速排序),由 Vladimir Yaroslavskiy 在 JDK 7 引入。它选两个基准值划分三段,比单轴快排减少比较次数,平均时间复杂度 O(n log n),最坏 O(n²),但实际极少触发;不稳定,相同值顺序可能改变。 - String[]、Person[] 等对象数组:默认使用 TimSort,即归并排序 + 插入排序的混合体。它能识别已有序片段(runs),合并时跳过冗余操作,时间复杂度稳定在 O(n log n),空间复杂度 O(n),且稳定——相同元素相对位置不变。
- 传入 Comparator 的任何数组(包括基本类型包装类如 Integer[]):统一走 TimSort 路径,哪怕你排序的是 int 的包装类,也按对象处理,保证稳定性。
小数组自动切插入排序,大数组才启动主算法
无论双轴快排还是 TimSort,内部都嵌入了阈值判断:
- 当待排序子段长度 ≤ 47(JDK 8 默认值),直接用插入排序——因为小规模下插入排序常数更小、局部性更好;
- 双轴快排还会在递归深度过大时降级为堆排序,避免最坏情况栈溢出;
- TimSort 对 run 长度做预扫描,若天然有序段足够长,会大幅减少合并次数。
常见误区与实战建议
写代码时容易忽略这些细节:
立即学习“Java免费学习笔记(深入)”;
- 别对基本类型数组依赖稳定性:比如你有多个值为 5 的元素,排序后它们的相对顺序无法保证;若业务需要保持原序(如先录入的排前面),应改用 Integer[] + Comparator 或自定义索引结构。
-
排序范围控制要小心:Arrays.sort(arr, from, to) 中
to是**不包含**的右边界,不是长度。例如 sort(arr, 1, 4) 只排索引 1、2、3 三个元素。 - 原地修改,无返回值:Arrays.sort() 永远修改原数组,不生成新数组。想保留原始顺序?得先 clone 或 Arrays.copyOf。
- null 元素在对象数组中会抛 NullPointerException:除非 Comparator 显式处理 null,否则 TimSort 在比较阶段就会崩。


















