您现在的位置是:首页 > 优选问答网站首页优选问答
java 数组排序 原理与实现详解
- 编辑:蒲亨云
- 2026-11-08 15:46:36
- 来源:网易
Java 数组排序主要分为两大类,一类是调用 JDK 自带的工具方法,也就是 Arrays 类提供的 sort 方法,这是实际开发最常用的方式,另一类是手写排序算法,比如冒泡排序 选择排序 插入排序,多用于学习算法原理和面试场景,原生数组本身没有内置 sort 成员方法,必须借助工具类或者自己编写循环交换逻辑完成排序。之所以要学习 java 数组排序,是因为数组是 Java 最基础的数据结构,业务开发经常需要对数字 字符串 自定义对象数组做升序降序处理,同时排序也是算法基础,理解排序可以掌握比较 交换 循环边界这些编程思维,JDK 内置 sort 经过底层优化,性能远高于新手手写的基础排序算法,正式项目优先使用 Arrays.sort。学习的时候可以分步骤推进,第一步掌握 Arrays.sort 基础用法,理解升序默认规则;第二步学习自定义比较器实现降序和对象排序;第三步手写冒泡 选择 插入排序,理解每一种算法的执行过程 时间复杂度;第四步区分基本类型数组和引用类型数组排序的底层差异。总的来说日常开发优先使用 java 数组排序自带 API,面试学习阶段需要掌握手写排序算法,并且清楚不同排序算法优缺点,根据数据规模和业务需求选择合适方案。
一 JDK 自带 Arrays.sort 用法
Arrays 是 java.util 包下面的工具类,专门处理数组操作,sort 是 java 数组排序最核心的方法,支持基本数据类型数组,也支持对象数组。
| 方法重载形式 | 适用类型 | 说明 |
|---|---|---|
| sort(int[] a) | int 数组 | 默认升序,原地排序,直接修改原数组 |
| sort(double[] a) | double 数组 | 默认升序 |
| sort(char[] a) | char 数组 | 按照字符编码升序 |
| sort(T[] a, Comparator super T> c) | 对象数组 | 传入比较器,可以自定义升序降序规则 |
| sort(int[] a, fromIndex, toIndex) | int 数组 | 局部排序,只排序指定下标区间,包含起始下标,不包含结束下标 |
基础示例要点
基本类型数组调用 Arrays.sort 之后默认从小到大升序,如果想要降序,基本类型不能直接使用比较器,一般做法是先升序,再反转数组,或者转为包装类 Integer 数组再使用 Comparator 降序。
对象数组比如 String 数组,默认按照字典序排序,如果是自定义实体类数组,必须实现 Comparable 接口,或者在 sort 里面传入 Comparator 比较器,否则会抛出类型转换异常。
二 手写经典排序算法
这部分是 java 数组排序学习重点,面试经常要求手写代码
| 算法名称 | 核心思想 | 时间复杂度 | 稳定性 |
|---|---|---|---|
| 冒泡排序 | 相邻元素两两比较,大的元素逐步移动到末尾 | 最好 O (n) 最坏 O (n²) | 稳定 |
| 选择排序 | 每一轮选出最小元素,和当前位置元素交换 | O(n²) | 不稳定 |
| 插入排序 | 把数组分成有序区和无序区,逐个把无序元素插入有序区合适位置 | 最好 O (n) 最坏 O (n²) | 稳定 |
| 快速排序 | 选取基准值,分区递归排序左右子数组 | 平均 O (nlogn) 最坏 O (n²) | 不稳定 |
冒泡排序实现思路
外层循环控制轮次,内层循环做相邻比较,如果前一个元素大于后一个就交换,每一轮结束之后最大元素沉到数组尾部,可以增加标记优化,如果一轮没有发生交换,说明数组已经有序,直接提前退出循环。
选择排序实现思路
每一轮遍历找到最小值下标,遍历完成之后把最小值和本轮起始位置元素交换,循环重复,不需要频繁交换,交换次数比冒泡排序更少。
插入排序实现思路
从第二个元素开始,把当前元素当成待插入值,向前遍历有序部分,如果前面元素大于待插入值就后移,找到空位插入,适合基本已经有序的数组。
三 基本类型数组和对象数组排序底层区别
基本类型数组,比如 int long double,Arrays.sort 底层使用双轴快速排序,专门针对原始数值类型优化。
对象引用类型数组,Arrays.sort 底层使用 TimSort,是归并排序优化版本,稳定排序,适合对象排序,稳定排序的含义是相等元素排序之后保留原本相对顺序。
这个底层差异是 java 数组排序很容易忽略的知识点,很多初学者以为所有 sort 底层都是同一种算法。
四 降序实现方案
方案一 包装类数组 Integer [] arr,使用 Arrays.sort (arr, Collections.reverseOrder ()) 实现降序
方案二 先 Arrays.sort 升序,然后循环反转数组,适合 int 基础类型数组
方案三 自定义 Comparator,重写 compare 方法,返回值反向比较
五 常见坑点
1 数组是原地排序,Arrays.sort 执行之后原数组内容会被修改,不会生成新数组
2 局部排序下标 toIndex 是开区间,很容易出现下标越界错误
3 自定义对象没有实现 Comparable,直接调用 Arrays.sort 会报 ClassCastException
4 手写排序的时候边界写错,出现数组下标越界,或者最后一轮重复比较
5 基本数据类型不能直接传入 Comparator 比较器,必须转成包装类数组
【常见问题】
问题 1 java 数组排序里面 Arrays.sort 是升序还是降序
回答 1 java 数组排序使用 Arrays.sort 默认是升序,如果需要降序,java 数组排序可以通过比较器或者反转数组实现,基本类型 int 数组不能直接使用比较器降序,需要转换成 Integer 包装类数组。
问题 2 java 数组排序手写冒泡排序时间复杂度是多少
回答 1 java 数组排序手写冒泡排序最坏和平均时间复杂度是 O (n²),如果数组本身已经有序,优化版本冒泡排序可以达到 O (n),数据量很大的时候,java 数组排序优先使用 Arrays.sort 性能更好。
问题 3 java 数组排序为什么自定义对象会报错
回答 1 java 数组排序如果是自定义对象数组,对象类需要实现 Comparable 接口,或者调用 sort 的时候传入 Comparator 比较器,缺少比较规则,java 数组排序就无法判断元素大小,运行抛出类型转换异常。
问题 4 java 数组排序之后原数组会改变吗
回答 1 java 数组排序调用 Arrays.sort 属于原地排序,排序之后原数组元素顺序会直接修改,java 数组排序不会自动生成一份新数组,如果需要保留原始顺序,需要提前复制一份新数组再排序。
【免责申明】
本文介绍的 java 数组排序相关原理和算法仅作为编程学习参考,不同 JDK 版本 Arrays.sort 底层实现可能存在调整,代码示例仅演示基础逻辑,生产项目请结合业务需求选择排序方案,本文不构成性能优化以及面试答题的保证。