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(", ");
   }
}
posted @ 2020-05-26 22:34  JL916  阅读(266)  评论(0编辑  收藏  举报