1. 概述
Arrays.sort()
是我们日常开发中再熟悉不过的工具,用于对对象或基本类型数组进行排序。JDK 8 引入了一个新方法 —— Arrays.parallelSort()
,旨在利用多核优势提升排序性能。
本文将深入对比 sort()
和 parallelSort()
的行为差异、底层机制及适用场景,帮你避免踩坑,做出更合理的技术选型。
2. Arrays.sort()
Arrays.sort()
用于对数组进行排序,底层采用的是 Dual-Pivot Quicksort(双轴快排) 算法 —— 这是 Java 团队对经典快排的优化实现,性能优于传统单轴快排。
✅ 关键特性:
- 单线程执行,不启用并发
- 提供两个重载方法:
sort(array)
:对整个数组排序sort(array, fromIndex, toIndex)
:仅对指定范围[fromIndex, toIndex)
排序
示例代码
@Test
public void givenArrayOfIntegers_whenUsingArraysSortMethod_thenSortFullArrayInAscendingOrder() {
int[] array = { 10, 4, 6, 2, 1, 9, 7, 8, 3, 5 };
int[] expected = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Arrays.sort(array);
assertArrayEquals(expected, array);
}
@Test
public void givenArrayOfIntegers_whenUsingArraysSortWithRange_thenSortRangeOfArrayAsc() {
int[] array = { 10, 4, 6, 2, 1, 9, 7, 8, 3, 5 };
int[] expected = { 10, 4, 1, 2, 6, 7, 8, 9, 3, 5 };
Arrays.sort(array, 2, 8);
assertArrayEquals(expected, array);
}
优缺点总结
✅ 优点 | ❌ 缺点 |
---|---|
小数据集下性能优异 | 大数据集性能下降明显 |
实现简单,开销低 | 无法利用多核 CPU 并行能力 |
⚠️ 注意:sort()
是纯同步操作,不会创建额外线程,适合大多数常规场景。
3. Arrays.parallelSort()
Arrays.parallelSort()
同样用于数组排序,API 设计与 sort()
完全一致,也支持全数组和区间排序。
示例代码
@Test
public void givenArrayOfIntegers_whenUsingArraysParallelSortMethod_thenSortFullArrayInAscendingOrder() {
int[] array = { 10, 4, 6, 2, 1, 9, 7, 8, 3, 5 };
int[] expected = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Arrays.parallelSort(array);
assertArrayEquals(expected, array);
}
@Test
public void givenArrayOfIntegers_whenUsingArraysParallelSortWithRange_thenSortRangeOfArrayAsc() {
int[] array = { 10, 4, 6, 2, 1, 9, 7, 8, 3, 5 };
int[] expected = { 10, 4, 1, 2, 6, 7, 8, 9, 3, 5 };
Arrays.parallelSort(array, 2, 8);
assertArrayEquals(expected, array);
}
底层原理
parallelSort()
采用的是 并行归并排序(parallel sort-merge)算法,核心流程如下:
- 将数组拆分为多个子任务
- 使用
ForkJoinPool
并行处理每个子任务的排序 - 最终将有序子数组合并成完整有序数组
⚠️ 但并行不是无条件启用的!JVM 有明确阈值控制:
- 若数组长度 ≤ 8192
- 或 CPU 只有单核
👉 则退化为 单线程的 Dual-Pivot Quicksort,避免并发开销反噬性能。
优缺点总结
✅ 优点 | ❌ 缺点 |
---|---|
大数据集下显著提升性能 | 小数组反而更慢(线程调度开销) |
充分利用多核 CPU 资源 | 内存占用略高(归并需要辅助空间) |
💡 简单粗暴地说:数据越大,并行收益越高;数据越小,越容易翻车。
4. 性能对比
以下数据基于 JMH 基准测试(Benchmark),环境为:
- CPU:AMD A10 PRO 2.1GHz 四核
- JDK:1.8.0_221
数组大小 | Arrays.sort() (ms) |
Arrays.parallelSort() (ms) |
---|---|---|
1,000 | 0.048 | 0.054 |
10,000 | 0.847 | 0.425 |
100,000 | 7.570 | 4.395 |
1,000,000 | 65.301 | 37.998 |
关键结论:
- ✅ 小数据(< 1万):
sort()
更快,parallelSort()
因线程开销反而拖慢 - ✅ 中大型数据(≥ 10万):
parallelSort()
性能优势明显,提速接近 40%~45% - ⚠️ 并行收益取决于 CPU 核心数和数据规模,不是“用了就快”
5. 总结与建议
场景 | 推荐方法 | 理由 |
---|---|---|
数组长度 < 10,000 | Arrays.sort() |
避免并发开销,性能更稳 |
数组长度 ≥ 100,000 | Arrays.parallelSort() |
多核并行优势显著 |
不确定数据规模 | 优先 sort() ,压测验证 |
实际性能受硬件影响大,别想当然 |
✅ 最佳实践建议:
- 日常开发中,小数组一律用
sort()
- 大数据批处理、排序密集型任务,考虑
parallelSort()
- 生产环境使用前务必做 JMH 压测,结合实际 CPU 和数据分布评估
所有示例代码已托管至 GitHub:https://github.com/johnchen/tutorials/tree/master/core-java-modules/core-java-arrays-sorting