Arrays.sort() 的一些用法

本文详细介绍了Java中Arrays.sort()方法的四种用法,包括基本类型的数组升序排序、指定范围排序、自定义比较器排序以及二维数组的排序。通过示例代码展示了如何实现降序排序、按照数组第一维或第二维排序,并解释了比较器在自定义排序规则中的应用。

Arrays.sort() 的一些用法

介绍

  • sort(T[] a):对指定T型数组按数字升序排序。
  • sort(T[] a,int formIndex, int toIndex):对指定T型数组的指定范围按数字升序排序。
  • sort(T[] a, Comparator<? supre T> c): 根据指定比较器产生的顺序对指定对象数组进行排序。
  • sort(T[] a, int formIndex, int toIndex, Comparator<? supre T> c): 根据指定比较器产生的顺序对指定对象数组的指定对象数组进行排序。

参数说明: 查看源码就知道重载的数据类型包括 Object 一共有八个,其他七个就是基本类型: int , long , short , char , byte , float , double .

1、sort(T[] a)

int[] ints = new int[]{12, 4, 6, 7, 2, 8, 3, 9};// 按 数字
char[] chars = new char[]{'a', 'c', 'b', 'i', '+'};// 按 ascii 码
byte[] bytes = new byte[]{7, 5, 6, 10, -1};// 按 字节数
Arrays.sort(ints);
Arrays.sort(chars);
Arrays.sort(bytes);
System.out.println(Arrays.toString(ints));
// 结果 :[2, 3, 4, 6, 7, 8, 9, 12]
System.out.println(Arrays.toString(chars));
// 结果 :[+, a, b, c, i]
System.out.println(Arrays.toString(bytes));
// 结果 :[-1, 5, 6, 7, 10]

2、sort(T[] a,int formIndex, int toIndex)

int[] ints = new int[]{12, 4, 6, 7, 2, 8, 3, 9};// 按 数字
char[] chars = new char[]{'a', 'c', 'b', 'i', '+'};// 按 ascii 码
byte[] bytes = new byte[]{7, 5, 6, 10, -1};// 按 字节数
Arrays.sort(ints, 2, 5);
Arrays.sort(chars, 2, 5);
Arrays.sort(bytes, 2, 5);
System.out.println(Arrays.toString(ints));
// 结果 :[12, 4, 2, 6, 7, 8, 3, 9]
System.out.println(Arrays.toString(chars));
// 结果 :[a, c, +, b, i]
System.out.println(Arrays.toString(bytes));
// 结果 :[7, 5, -1, 6, 10]

3、sort(T[] a, Comparator<? supre T> c)

根据指定比较器产生的顺序对指定对象数组进行排序.

(1). 一维数组降序排序

这里用降序演示一下;

 /*注意,要想改变默认的排列顺序,不能使用基本类型(int,double, char)
而要使用它们对应的包装类*/
Integer[] ints = new Integer[]{12, 4, 6, 7, 2, 8, 3, 9};
Arrays.sort(ints, Collections.reverseOrder());
System.out.println(Arrays.toString(ints));
// 结果 :[12, 9, 8, 7, 6, 4, 3, 2]

也可以使用自定义规则

Arrays.sort(ints, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1;
    }
});
// lambda 表达式
Arrays.sort(ints, (o1, o2) -> o2 - o1);

(2).二维数组按照第一维数组排序 升序

PS:这里提一下如果是 Integer数组 比较相等时用 equals 而不是用 == 。

int[][] nums=new int[][]{{1,3},{1,2},{5,1},{4,5},{3,3}};
//方法一
Arrays.sort(nums,new Comparator<int[]>(){
    @Override
    public int compare(int[] a,int[] b){
        // 当第一维相等时比较第二维的
        if(a[0] == b[0]){
            return a[1]-b[1];
        }else{
            return a[0]-b[0];
        }
    }
});

// 方法二,使用 lambda 表达式
Arrays.sort(nums,(a,b) -> a[0] == b[0] ? a[1]-b[1] : a[0]-b[0]);
for (int[] num : nums) {
    System.out.print(Arrays.toString(num));
}
// 结果 : [1, 2][1, 3][3, 3][4, 5][5, 1]

(3).二维数组按照第二维数组排序 升序

int[][] nums=new int[][]{{1,3},{1,2},{5,1},{4,5},{3,3}};
//方法一
Arrays.sort(nums,new Comparator<int[]>(){
    @Override
    public int compare(int[] a,int[] b){
        // 当第二维相等时比较第一维的
        if(a[1] == b[1]){
            return a[0]-b[0];
        }else{
            return a[1]-b[1];
        }
    }
});

// 方法二,使用 lambda 表达式
Arrays.sort(nums,(a,b) -> a[1] == b[1]  ? a[0]-b[0] : a[1]-b[1]);
for (int[] num : nums) {
    System.out.print(Arrays.toString(num));
}
// 结果 : [5, 1][1, 2][1, 3][3, 3][4, 5]

(4).二维数组 降序

对调返回值哪里的顺序
也就是:

// 按第一维降序
if(a[0].equals(b[0]){
    return b[1]-a[1];
}else{
    return b[0]-a[0];
}
// 结果 : [5, 1][4, 5][3, 3][1, 3][1, 2]

(5). 类的比较

其实这个方法最重要的还是类对象的比较
由于我们可以自定义比较器,所以我们可以使用策略模式,使得在运行时选择不同的算法
这里就不说明了,会开个新随笔记录.

4、sort(T[] a, int formIndex, int toIndex, Comparator c)

这里就不用代码说明了,就是根据指定比较器产生的顺序对指定对象数组的指定对象数组进行排序。

<think>我们正在讨论Java中的Arrays.sort方法。根据用户需求,需要介绍其使用方法和原理,并参考提供的引用内容。 引用内容摘要: [^1]: 介绍了Arrays.sort()方法的使用场景、定义等,但标题是"Java实战入门:深入解析Java中的 `Arrays.sort()` 方法",说明它可能是关于Arrays.sort的详细解析。 [^2]: 提到Arrays.sort()和Collections.sort()的底层原理,指出基本类型数组和对象数组的排序方式不同,基本类型用快速排序的变体,对象用归并排序(但注意,实际在Java中,对象数组排序在早期版本是归并,后来改为TimSort)。 [^3]: 明确说明不论是Collections.sort方法或者是Arrays.sort方法,底层实现都是TimSort实现的(这是jdk1.7新增的),以前是归并排序。并解释了TimSort算法的基本思想:找到已经排好序数据的子序列(run),然后对剩余部分排序,再合并。 [^4]: 提到Arrays.sort()对快速排序的优化,特别是处理相等元素的优化(使得相等的元素能够放在附近,从而减少不必要的交换)。 [^5]: 列举了Collections类中的其他方法(如混排、反转等),但并没有直接关于Arrays.sort原理的更多信息。 因此,我们可以组织答案如下: 1. 方法定义和使用场景: 根据[^1],Arrays.sort()用于对数组排序,支持基本数据类型数组和对象数组。 2. 使用方法: 基本数据类型数组:直接使用Arrays.sort(数组) 对象数组:需要对象实现Comparable接口,或者提供Comparator 3. 实现原理(重点): 根据[^2][^3][^4]: - 对于基本数据类型数组:使用双轴快速排序(Dual-Pivot Quicksort),这是对经典快速排序的优化,由Vladimir Yaroslavskiy在2009年提出。它使用两个基准元素将数组分成三部分,然后递归排序。这种算法在大多数情况下比传统单轴快速排序更快,特别是对于大量数据。同时,它也对连续相等元素做了优化(避免不必要的交换)[^4]。 - 对于对象数组:使用TimSort算法(从Java 7开始)。TimSort是一种归并排序和插入排序的混合排序算法,它利用了数据中已存在的有序片段(称为run),然后合并这些run。TimSort是稳定的排序算法(即相等元素的相对顺序不变)。 4. 示例代码: 分别展示基本类型数组和对象数组的排序。 5. 注意事项: - 对象数组排序时,如果没有实现Comparable接口,则必须在调用时提供Comparator,否则会抛出ClassCastException。 - 排序会直接修改原数组(原地排序)。 - 对于基本类型数组,排序算法是非稳定的,但对于对象数组,排序是稳定的(因为使用TimSort)。 6. 与Collections.sort()的关系: 根据[^2][^3],Collections.sort()底层也是调用Arrays.sort(),但是它是针对List接口的,内部会先将列表转换为数组,然后使用Arrays.sort()排序,最后将排序后的数组复制回列表。 7. 性能分析: - 时间复杂度:平均为$O(n \log n)$,最坏情况下,快速排序为$O(n^2)$,但双轴快速排序在实现中通过多种技巧(如小数组用插入排序、选择好的基准等)减少了最坏情况发生的概率。TimSort的最坏时间复杂度也是$O(n \log n)$,最好情况(已经有序)是$O(n)$。 - 空间复杂度:双轴快速排序是$O(\log n)$(递归栈),TimSort是$O(n)$(因为归并排序需要额外的空间)。 根据以上思路,我们组织答案。 </think>### Java中`Arrays.sort()`方法解析 `Arrays.sort()`是Java中用于数组排序的核心方法,支持基本类型数组和对象数组的高效排序。以下从使用方法和底层原理两方面深入解析。 --- #### 一、使用方法 ##### 1. **基本类型数组排序** 直接调用`Arrays.sort()`,默认升序排序: ```java int[] numbers = {5, 2, 9, 1}; Arrays.sort(numbers); // 原地排序,结果为[1, 2, 5, 9] ``` - **支持类型**:`int[]`、`double[]`、`char[]`等基本类型数组[^1]。 ##### 2. **对象数组排序** 对象数组需满足以下条件之一: - **实现`Comparable`接口**: ```java class Person implements Comparable<Person> { String name; int age; // 实现compareTo方法定义自然顺序 @Override public int compareTo(Person other) { return Integer.compare(this.age, other.age); } } Person[] people = new Person[]{...}; Arrays.sort(people); // 按年龄升序 ``` - **提供`Comparator`**: ```java Arrays.sort(people, Comparator.comparing(Person::getName)); // 按姓名排序 Arrays.sort(people, Comparator.comparingInt(Person::getAge).reversed() // 按年龄降序 ); ``` ⚠️ **未实现`Comparable`且未提供`Comparator`会抛出`ClassCastException`**[^1][^2]。 ##### 3. **部分排序** 对数组指定区间排序: ```java int[] arr = {7, 3, 8, 2, 5}; Arrays.sort(arr, 1, 4); // 对索引[1,4)排序 → [7, 2, 3, 8, 5] ``` --- #### 二、底层原理 根据数组类型选择不同算法: ##### 1. **基本类型数组:双轴快速排序(Dual-Pivot Quicksort)** - **核心思想**:使用两个基准值(pivot)将数组分为三部分: $$ \text{左侧} < \text{Pivot1} \leq \text{中间} < \text{Pivot2} \leq \text{右侧} $$ 递归处理子数组[^2][^4]。 - **优化点**: - 小数组(长度<47)转插入排序减少递归开销 - 处理连续相等元素时减少交换次数[^4] - **时间复杂度**: - 平均:$O(n \log n)$ - 最坏:$O(n^2)$(概率极低) ##### 2. **对象数组:TimSort算法** - **核心思想**:归并排序 + 插入排序优化[^3]: 1. **寻找有序子序列(Run)**:扫描数组识别升序/降序片段 2. **插入排序优化**:短序列(长度<32)用二分插入排序 3. **归并合并**:按规则合并相邻有序子序列 - **优势**: - 稳定排序(相等元素顺序不变) - 对部分有序数据效率接近$O(n)$[^3] - **时间复杂度**:最坏$O(n \log n)$ --- #### 三、关键注意事项 1. **原地排序**:直接修改原数组,无返回值[^1][^2]。 2. **稳定性差异**: - 对象数组排序**稳定**(TimSort特性) - 基本类型数组排序**非稳定** 3. **性能对比**: | 场景 | 推荐方法 | 原因 | |-------------------|-------------------|--------------------------| | 基本类型大数组 | `Arrays.sort()` | 双轴快排缓存命中率高 | | 对象数组/链式排序 | `Collections.sort()` | 底层调用`Arrays.sort()` | [^2][^5] --- #### 四、示例场景 ```java // 混合排序:先按姓名升序,再按年龄降序 Arrays.sort(people, Comparator.comparing(Person::getName) .thenComparing(Comparator.comparingInt(Person::getAge).reversed()) ); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慢慢变富的w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值