定义
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) 时不会再分。
方法
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
}
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) { /* */ }
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) { /* */ }
// 实现与 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) { /* */ }
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;
}
public static int hashCode(int a[]) {
if (a == null)
return 0;
int result = 1;
for (int element : a)
result = 31 * result + element;
return result;
}
// 同样 基本类型利用 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]
// 因为是并行修改 所以如果与其他下标相关 不能保证数据正确
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 双轴快速排序
public static void setAll(int[] array, IntUnaryOperator generator) {
Objects.requireNonNull(generator);
for (int i = 0; i < array.length; i++)
array[i] = generator.applyAsInt(i);
}
// 同样使用双轴快速排序
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);
}
public static <T> Spliterator<T> spliterator(T[] array) { /* */ }
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);
}
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(", ");
}
}