• Java源码学习(JDK 11)——java.util.Arrays


    定义

    package java.util;
    
    public class Arrays {
    
         private Arrays() {}
    }
    
    • 工具类,辅助实现数组相关操作,如:排序(sort),查找(binarySearch),比较(compare),复制(copyOf),相等(equals),填充(fill)等。
    • 构造器私有,保证无法实例化,使用时直接使用静态方法。
    • 方法被 static 修饰。

    属性

    /**
    * Tuning parameter: list size at or below which insertion sort will be
    * used in preference to mergesort.
    * To be removed in a future release.
    */
    private static final int INSERTIONSORT_THRESHOLD = 7; 
    
    /**
    * The minimum array length below which a parallel sorting
    * algorithm will not further partition the sorting task. Using
    * smaller sizes typically results in memory contention across
    * tasks that makes parallel speedups unlikely.
    */
    private static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
    
    • 工具类的属性是常量
    • INSERTIONSORT_THRESHOLD 代表排序时使用插入算法的门限,<= 7 时使用插入排序而非归并排序。(即将被移除)
    • MIN_ARRAY_SORT_GRAN 并行排序时分割任务的门限,<= (1 << 13) 时不会再分。

    方法

    • asList 数组转为 List
    public static <T> List<T> asList(T... a) {
       return new ArrayList<>(a); 
       // 该 ArrayList 是内部类实现
       // 直接使用该数组作为 ArrayList 底层的数组
       // 相当于为数组提供了 List 的 API 但不允许添加删除元素等操作
    }
    
    // 使用
    
    Integer[] a = { 1, 2, 3, 4, 5 };
    System.out.println(Arrays.asList(a));   
    // 正确输出:[1, 2, 3, 4, 5]
    
    int[] a = { 1, 2, 3, 4, 5 };
    System.out.println(Arrays.asList(a));   
    // 错误输出:[[I@4dc63996] 直接将 int[] 作为1个元素
    
    • binarySearch 二分查找 要求数组必须有序
    public static int binarySearch(int[] a, int key) {
       return binarySearch0(a, 0, a.length, key);
    }
    
    public static int binarySearch(int[] a, int fromIndex, int toIndex, int key) {
       rangeCheck(a.length, fromIndex, toIndex);
       return binarySearch0(a, fromIndex, toIndex, key);
    }
    
    private static int binarySearch0(int[] a, int fromIndex, int toIndex, int key) {
       int low = fromIndex;
       int high = toIndex - 1;
    
       while (low <= high) {
           int mid = (low + high) >>> 1;
           int 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.
       // low 为插入位置 即插入位置 = - res - 1
    }
    
    • compare 数组元素比较
    public static int compare(int[] a, int[] b) {
       if (a == b)
           return 0;
       if (a == null || b == null)
           return a == null ? -1 : 1;
    
       int i = ArraysSupport.mismatch(a, b, Math.min(a.length, b.length));  // 找到第一个不同的下标
       if (i >= 0) {
           return Integer.compare(a[i], b[i]);
       }
    
       return a.length - b.length;
    }
    
    public static int compare(int[] a, int aFromIndex, int aToIndex, 
                              int[] b, int bFromIndex, int bToIndex) {
         rangeCheck(a.length, aFromIndex, aToIndex);
         rangeCheck(b.length, bFromIndex, bToIndex);
         // ... 
         // 实现类似
    }
    
    // 非基本类型不使用 mismatch 方法 直接使用 compareTo 进行比较
    
    // 无符号数
    public static int compareUnsigned(int[] a, int[] b) { /* */ }
    public static int compareUnsigned(int[] a, int aFromIndex, int aToIndex, 
                                      int[] b, int bFromIndex, int bToIndex) { /* */ }
    
    • copyOf 数组复制
    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;
    }
    
    public static int[] copyOfRange(int[] original, int from, int to) {
       int newLength = to - from;
       if (newLength < 0)
           throw new IllegalArgumentException(from + " > " + to);
       int[] copy = new int[newLength];
       System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
       return copy;
    }
    
    // 内部使用 System.arraycopy
    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length) { /* */ }
    
    • equals 数组元素相等
    // 实现与 compare 类似 
    // 基本类型利用 ArraysSupport.mismatch 方法 其他类型使用 Objects.equals
    public static boolean equals(int[] a, int[] a2) {
       if (a==a2)
           return true;
       if (a==null || a2==null)
           return false;
    
       int length = a.length;
       if (a2.length != length)
           return false;
    
       return ArraysSupport.mismatch(a, a2, length) < 0;
    }
    
    public static boolean equals(int[] a, int aFromIndex, int aToIndex,
                                 int[] b, int bFromIndex, int bToIndex) { /* */ }
    
    // deepEquals 适合嵌套数组使用
    public static boolean deepEquals(Object[] a1, Object[] a2) { /* */ }
    
    • fill 数组填充
    public static void fill(int[] a, int val) {
       for (int i = 0, len = a.length; i < len; i++)
           a[i] = val;
    }
    
    public static void fill(int[] a, int fromIndex, int toIndex, int val) {
       rangeCheck(a.length, fromIndex, toIndex);
       for (int i = fromIndex; i < toIndex; i++)
           a[i] = val;
    }
    
    • hashcode 哈希值
    public static int hashCode(int a[]) {
       if (a == null)
           return 0;
    
       int result = 1;
       for (int element : a)
           result = 31 * result + element;
    
       return result;
    }
    
    • mismatch 寻找第一个不同的元素下标
    // 同样 基本类型利用 ArraysSupport.mismatch Object 利用 Objects.equals
    public static int mismatch(int[] a, int[] b) {
       int length = Math.min(a.length, b.length); // Check null array refs
       if (a == b)
           return -1;
    
       int i = ArraysSupport.mismatch(a, b, length);
       return (i < 0 && a.length != b.length) ? length : i;
    }
    
    public static int mismatch(int[] a, int aFromIndex, int aToIndex,
                               int[] b, int bFromIndex, int bToIndex) { /* */ }
    
    • parallelPrefix 并行地累积计算给定数组中的每个元素
    /**
    * Cumulates, in parallel, each element of the given array in place,
    * using the supplied function. For example if the array initially
    * holds {@code [2, 1, 0, 3]} and the operation performs addition,
    * then upon return the array holds {@code [2, 3, 3, 6]}.
    * Parallel prefix computation is usually more efficient than
    * sequential loops for large arrays.
    *
    * @param array the array, which is modified in-place by this method
    * @param op a side-effect-free, associative function to perform the
    * cumulation
    * @throws NullPointerException if the specified array or function is null
    * @since 1.8
    */
    public static void parallelPrefix(int[] array, IntBinaryOperator op) {
       Objects.requireNonNull(op);
       if (array.length > 0)
           new ArrayPrefixHelpers.IntCumulateTask(null, op, array, 0, array.length).invoke();
    }
    
    public static void parallelPrefix(int[] array, int fromIndex, int toIndex, IntBinaryOperator op) { /* */ }
    
    // 使用
    int[] a = { 1, 2, 3, 4, 5 };
    Arrays.parallelPrefix(a, (l, r) -> l * r);
    // 阶乘:[1,2,6,24,120]
    
    • parallelSetAll 并行批量修改数组元素
    public static void parallelSetAll(int[] array, IntUnaryOperator generator) {
       Objects.requireNonNull(generator);
       IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsInt(i); });
    }
    
    // 使用
    int[] a = { 1, 2, 3, 4, 5 };
    Arrays.parallelSetAll(a, (index) -> a[index] << 1);
    // 翻倍:[2,4,6,8,10]
    // 因为是并行修改 所以如果与其他下标相关 不能保证数据正确
    
    • parallelSort 并行排序
    public static void parallelSort(int[] a) {
       int n = a.length, p, g;
       // 数组元素个数超过 MIN_ARRAY_SORT_GRAN 才可能并行排序
       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();
    }
    
    public static void parallelSort(int[] a, int fromIndex, int toIndex) { /*  */ }
    
    // DualPivotQuicksort 双轴快速排序
    
    • setAll 批量修改数组元素
    public static void setAll(int[] array, IntUnaryOperator generator) {
       Objects.requireNonNull(generator);
       for (int i = 0; i < array.length; i++)
           array[i] = generator.applyAsInt(i);
    }
    
    • sort 排序
    // 同样使用双轴快速排序
    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);
    }
    
    • spliterator 可分割迭代器
    public static <T> Spliterator<T> spliterator(T[] array) { /* */ }
    
    • stream
    public static IntStream stream(int[] array) {
       return stream(array, 0, array.length);
    }
    
    public static IntStream stream(int[] array, int startInclusive, int endExclusive) {
       return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false);
    }
    
    • toString 字符串
    public static String toString(int[] a) {
       if (a == null)
           return "null";
       int iMax = a.length - 1;
       if (iMax == -1)
           return "[]";
    
       StringBuilder b = new StringBuilder();
       b.append('[');
       for (int i = 0; ; i++) {
           b.append(a[i]);
           if (i == iMax)
               return b.append(']').toString();
           b.append(", ");
       }
    }
    
  • 相关阅读:
    C#如何防止程序多次运行的技巧
    C#导出Excel按照指定格式设置单元格属性值
    js前台遍历后台返回的Datatable数据
    Datatable数据分组
    DataTable 详解(转)
    遍历Datatable
    DataTable转Json
    键值集合List转换成datatable
    DataTable转换成实体
    泛型集合与DataSet相互转换
  • 原文地址:https://www.cnblogs.com/JL916/p/12969188.html
Copyright © 2020-2023  润新知