Arrays源码阅读(TODO)


Arrays这边主要看方法实现

一.方法实现

1.binarySearch0

这边就直接看支持泛型的binarySearch0,因为Arrays里面有很多binarySearch的重载,支持泛型的应该是最能看出问题的
二分查找的默认前提是排序好的数组
直接上代码:

/**
     * 前面的调用函数做了一些列的长度检查,这边就是直接的二分法查找操作 -- 二分法的前提是排序好得数组
     * @param a 被查找的数组
     * @param fromIndex 从哪个位置开始查找
     * @param toIndex 查找结束的位置
     * @param key 要查找的元素
     * @param c 比较规则,比如int就是 > = <这样
     * @param <T> 查找泛型
     * @return 返回查找到的元素
     */
    private static <T> int binarySearch0(T[] a, int fromIndex, int toIndex,
                                         T key, Comparator<? super T> c) {
        //1.如果没有匹配规则,就按照Object的方式去匹配
        if (c == null) {
            return binarySearch0(a, fromIndex, toIndex, key);
        }
        //2.设值低位和高位
        int low = fromIndex;
        int high = toIndex - 1;

        //3.当低位一直小于高位的时候,循环
        while (low <= high) {
            //4.找到中间位置下标和对应元素
            int mid = (low + high) >>> 1;
            T midVal = a[mid];
            //5.比较
            int cmp = c.compare(midVal, key);
            //6.如果小则低位 = 中间位置+1;如果大则高位 = 中间位置-1;相等则返回
            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }
2.sort

sort方法这边有两种实现,一种是归并排序,一种是timsort;我们分别来看两种排序方法

    public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            //这边主要关注两个排序方法
            //1.merge sort是归并排序,通过System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");设置
            //归并排序它的时间复杂度(最优、平均、最差)都是O(n log n),但是需要整块数组空间参与
            //2.tim sort是归并排序+插入排序的优化
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }
1.mergesort,归并排序

归并排序的排序思想就是分堆,然后堆之间排序,通过递归实现所有堆的排序,他的算法过程大概是这样的:

  • 大数组进来(长度大于7),从中间切开,分成两个中数组
  • 递归调用每个中数组(长度大于7),从中间切开,分成两个小数组
  • 小数组(长度小于7),进行快速排序,返回
  • 回到中数组,这边有一个快排的优化,就是判断两个小数组,前一个的最后一位是否小于后一个的第一位,如果是,说明无需排序,直接copy即可
  • 上述不满足的话,则循环小数组,从第一位开始比较,小的元素添加到新数组,下标后移,直到结束
  • 重复上述步骤,直到递归结束

图示:
在这里插入图片描述

 private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low, int high, int off,
                                  Comparator c) {
        int length = high - low;

        // 1.如果数组长度小于7,使用插入排序
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        //2.把数组拆分成两个小数组,进入递归
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);

        //3.这边是对快排的结果做一个优化,如果直接是有序的,只要copy数组就行
        if (c.compare(src[mid-1], src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        //4.低位和mid位置进行比较,因为归并之后,大数组包含两个小数组,前后两个小数组是各自有序的
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }
2.timsort:归并和快排的结合

不是很能理解,以后再补充吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
arrays.copyOf是Java中的一个方法,用于复制一个数组。 它的源码如下: ```java public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); } public static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; } ``` 首先,copyOf方法是一个重载的方法,它有两个版本。第一个版本传入两个参数,分别是原始数组和新数组的长度。第二个版本传入三个参数,分别是原始数组,新数组的长度以及新数组的类型。 在第一个版本中,方法内部调用了第二个版本的方法,并且将原始数组的类型传递给了新数组的类型。 在第二个版本中,根据新数组的类型创建了一个新的数组对象copy。如果新数组的类型是Object数组,则直接创建一个新的Object数组;如果新数组的类型不是Object数组,则通过Array.newInstance方法创建指定类型的新数组。 然后,使用System.arraycopy方法将原始数组的元素复制到新数组中。该方法会复制原始数组的前Math.min(original.length, newLength)个元素,确保不会超出新数组的长度。 最后,将复制后的数组返回。 总结来说,arrays.copyOf方法就是根据给定的原始数组和长度复制出一个新的数组,并返回该新数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

了-凡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值