Java中Arrays.sort()的四种用法&深入源码理解

1.Arrays.sort()

Java的Arrays类中有一个sort()方法,该方法是Arrays类的静态方法,在需要对数组进行排序时,非常的好用。

1、Arrays.sort(int[] a)

这种形式是对一个数组的所有元素进行排序,并且是按从小到大的顺序。

sort()源码

    public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }

//点开legacyMergeSort 有一个数组的(浅)拷贝,然后就是归并排序
    private static void legacyMergeSort(Object[] a) {
        Object[] aux = a.clone();
        mergeSort(aux, a, 0, a.length, 0);   
    }
 // 点开mergeSort
// src 源数组
// dest 目标数组
// low 开始下标
// high 尾端下标
// off 偏移量 对数组指定位置进行排序需要用到这个。
    private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low,
                                  int high,
                                  int off) {
        // 数组区间的数据长度
        int length = high - low;

        //  这里是对归并排序的一个优化,因为在对于少量数据的数组使用插入排序的效率更高。
        //  所以这里加了一个插入排序的阈值为7
        
        if (length < INSERTIONSORT_THRESHOLD) {
        
        //  这里实现的是插入排序。将数组分为两个区间,其中一个为已排序区间,开始只有一个就是数组的
        // 第一个元素,其余的都为未排序区间,将未排序区间的每一个元素与已排序区间做比较,找到合适
        // 的位置插入
        
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
                         ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        
        // >>>1 表示做无符号位右移1 位 ,即除以2 .
        int mid = (low + high) >>> 1;
       
       // 这里进行递归排序,将 dest 数组的一半排序成 src数组  
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

    	// 这里是对归并排序的第二个优化部分。
    	// 即进行归并排序的两部分分别排序后
    	// 前半部分的最大值 小于 后半部分的最小值,即已经是有序数组,就直接将 排序后的src 数组 
    	// 复制 到dest 数组
        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        //  在这里将分别排序后的两个数组进行合并
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            // 前半部分值小
            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                dest[i] = src[p++];
            // 后半部分值小
            else
                dest[i] = src[q++];
        }
    }

在这里插入图片描述

归并排序的时间复杂度为O(nlogn).
归并排序的空间复杂度为O(n),从代码中可以看出,归并排序会复制一个原数组,多开辟出来一块内存空间。

2、Arrays.sort(int[] a, int fromIndex, int toIndex)

这种形式是对数组部分排序,也就是对数组a的下标从fromIndex到toIndex-1的元素排序,注意:下标为toIndex的元素不参与排序

降序

3.利用Collections.reverseOrder()方法:

Integer[] a = {1,2,3,4,5,6,7,8,9};
Arrays.sort(a,Collections.reverseOrder());
for(int arr:a) {
  System.out.print(arr + " ");
}
//点开reverseOrder
    public static <T> Comparator<T> reverseOrder() {
        return (Comparator<T>) ReverseComparator.REVERSE_ORDER;
    }
//继续看ReverseComparator
    private static class ReverseComparator
        implements Comparator<Comparable<Object>>, Serializable {

        @java.io.Serial
        private static final long serialVersionUID = 7207038068494060240L;

        static final ReverseComparator REVERSE_ORDER
            = new ReverseComparator();

        public int compare(Comparable<Object> c1, Comparable<Object> c2) {
            return c2.compareTo(c1);
        }
//Comparable是个接口,重写compareTo()方法
 public interface Comparable<T> {

    public int compareTo(T o);
}

4.实现Comparator接口的复写compare()方法:

    public static void main(String[] args) {
        Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
        //定义一个自定义类MyComparator的对象
        Comparator cmp = new MyComparator();
        Arrays.sort(a,cmp);
        for(int arr:a) {
            System.out.print(arr + " ");
        }
    }
//实现Comparator接口
class MyComparator implements Comparator<Integer>{
    @Override
    public int compare(Integer o1, Integer o2) {
    		        /*如果o1小于o2,我们就返回正值,如果o1大于o2我们就返回负值,
    		         这样颠倒一下,就可以实现降序排序了,反之即可自定义升序排序了*/
        //return o2.compareTo(o1);
        return o2-o1;
    }
}

compareTo()的返回值是整型,它是先比较对应字符的大小(ASCII码顺序),如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的 差值,如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方 全比较完,这时就比较字符的长度.

String s1 = "abc"; 
String s2 = "abcd"; 
String s3 = "abcdfg"; 
String s4 = "1bcdfg"; 
String s5 = "cdfg"; 
System.out.println( s1.compareTo(s2) ); // -1 (前面相等,s1长度小1) 
System.out.println( s1.compareTo(s3) ); // -3 (前面相等,s1长度小3) 
System.out.println( s1.compareTo(s4) ); // 48 ("a"的ASCII码是97,"1"的的ASCII码是49,所以返回48) 
System.out.println( s1.compareTo(s5) ); // -2 ("a"的ASCII码是97,"c"的ASCII码是99,所以返回-2)

看compareTo的源码

    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }

继续看compare的源码

    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

其实就是如果返回1,就是升序,-1则是降序。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值