0100 java.utils.Arrays 源码阅读笔记

Java Arrays源码阅读笔记

来自包 java.utils.Arrays
文字与代码对应关心:学习理解的文字在源代码的下方

   private static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
  • 最小数组长度,低于该长度,并行排序算法将不会进一步划分排序任务。使用较小的大小通常会导致任务之间的内存竞争,从而使并行加速变得不太可能。默认是2^13 = 8192个元素长度。

    private Arrays() {}
    
  • 取消默认构造函数,确保不可实例化。

private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
    if (fromIndex > toIndex) {
        throw new IllegalArgumentException(
                "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
    }
    if (fromIndex < 0) {
        throw new ArrayIndexOutOfBoundsException(fromIndex);
    }
    if (toIndex > arrayLength) {
        throw new ArrayIndexOutOfBoundsException(toIndex);
    }
}
  • 检查数组的索引范围是否正常,如果异常就抛出异常。

  • 专门把参数检查做成一个函数,满足代码复用、简洁的原则。
    抛出异常时指明具体异常,避免笼统的Exception。
        public static void sort(int[] a) {
            DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
        }
        public static void sort(int[] a, int fromIndex, int toIndex) {
            rangeCheck(a.length, fromIndex, toIndex);
            DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
        }
    
  • 对数组升序排序,此处使用了java.util.DualPivotQuicksort双枢轴快速排序算法,算法复杂度O(nlogn),比传统的单枢轴快排更快。

  • 提供int、long、short、char、byte、float、double数组的排序。

//672 line
public static void parallelSort(int[] a) {
    int n = a.length, p, g;
    if (n <= MIN_ARRAY_SORT_GRAN ||
        (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
        DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);
    else
        new ArraysParallelSortHelpers.FJInt.Sorter
            (null, a, new int[n], 0, n, 0,
             ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
             MIN_ARRAY_SORT_GRAN : g).invoke();
}
  • 平行排序算法:当数组长度小于最小粒度(MIN_ARRAY_SORT_GRAN)时,直接用双枢轴快排。反之将数组划分成小于最小粒度的子数组排序,最后再合并排序,此处利用了分治法实现并行排序
private static void mergeSort(Object[] src,
                              Object[] dest,
                              int low,
                              int high,
                              int off) {
    int length = high - low;

    // Insertion sort on smallest arrays
    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;
    int mid = (low + high) >>> 1;
    mergeSort(dest, src, low, mid, -off);
    mergeSort(dest, src, mid, high, -off);

    // If list is already sorted, just copy from src to dest.  This is an
    // optimization that results in faster sorts for nearly ordered lists.
    if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
        System.arraycopy(src, low, dest, destLow, length);
        return;
    }

    // Merge sorted halves (now in src) into dest
    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++];
    }
}
 private static void swap(Object[] x, int a, int b) {
        Object t = x[a];
        x[a] = x[b];
        x[b] = t;
    }
  • 旧版的合并排序,基于该排序的算法将被删除了。
public static int binarySearch(char[] a, int fromIndex, int toIndex,
                               char key) {
    rangeCheck(a.length, fromIndex, toIndex);
    return binarySearch0(a, fromIndex, toIndex, key);
}

// Like public version, but without range checks.
private static int binarySearch0(char[] a, int fromIndex, int toIndex,
                                 char key) {
    int low = fromIndex;
    int high = toIndex - 1;

    while (low <= high) {
        int mid = (low + high) >>> 1;
        char midVal = a[mid];

        if (midVal < key)
            low = mid + 1;
        else if (midVal > key)
            high = mid - 1;
        else
            return mid; // key found
    }
    return -(low + 1);  // key not found.
}
  • 在数组中查找目标值:此处使用了二分查找
public static boolean equals(long[] a, long[] a2) {
    if (a==a2)//同一个数组相等
        return true;
    if (a==null || a2==null)//null不等
        return false;

    int length = a.length;
    if (a2.length != length) //长度不等,则不同
        return false;

    for (int i=0; i<length; i++) 
        if (a[i] != a2[i]) //相同位置元素有不同则不等
            return false;

    return true; //否则相等
}
  • 判断两个数组是否相等
public static void fill(long[] a, long val) {
    for (int i = 0, len = a.length; i < len; i++)
        a[i] = val;
}
  • 数组填充:用值val填充数组a,复杂度O(n)
   public static int[] copyOf(int[] original, int newLength) {
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
  • 复制数组:将原始数组复制newLength个元素,使用了 System.arraycopy()的方法,返回新数组。
  • System.arraycopy(原始数组, 原始起始索引, 原始终止位置(终止索引+1), 目标数组起始索引,目标数组终止位置(终止索引+1));

3440 line……

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值