Arrays就是Java中的数组工具类,它包含了很多静态的方法来对数组进行操作。
下面我们来看看它对数组可以进行哪些操作。
1、将数组转换成一个List
public static List asList(T... array) {
return new ArrayList(array);
}
实质就是使用数组来创建了一个ArrayList。
2、数组元素查找系列
它提供了一系列的binarySearch函数来对数组进行二分查找。
3、数组复制系列
因为数组在定义的时候就已经固定了其长度,如果需要对数组大小进行扩充,就需要定义一个新的数组然后把旧数组的原始复制到新的数组。在Arrays里面就提供了copyOf和copyOfRange系列函数来进行数组的扩充。
4、数组比较
它提供了两种比较函数,一种是普通的equals函数,一种是深度比较deepEquals函数。
5、填充函数
它提供了fill系列函数来对数组的指定区间进行赋值,默认是整个区间。
public static void fill(int[] array, int start, int end, int value) {
checkFillBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
}
6、hashCode与deepHashCode函数
7、排序函数
它提供了一系列的sort函数进行排序使用
8、toString函数
下面我们来重点看看几类函数的实现
1、复制函数copyOf和copyOfRange
public static T[] copyOf(T[] original, int newLength) {
if (original == null) {
throw new NullPointerException();
}
if (newLength < 0) {
throw new NegativeArraySizeException();
}
return copyOfRange(original, 0, newLength);
}
本质使用的还是copyOfRange函数。
public static T[] copyOfRange(T[] original, int start, int end) {
int originalLength = original.length; // For exception priority compatibility.
if (start > end) {
throw new IllegalArgumentException();
}
if (start < 0 || start > originalLength) {
throw new ArrayIndexOutOfBoundsException();
}
int resultLength = end - start;
int copyLength = Math.min(resultLength, originalLength - start);
// 创建了一个新的数组
T[] result = (T[]) Array.newInstance(original.getClass().getComponentType(), resultLength);
// 将原数组的元素复制到新的数组
System.arraycopy(original, start, result, 0, copyLength);
// 最终将新数组返回
return result;
}
2、数组比较equals和deepEquals函数
public static boolean equals(Object[] array1, Object[] array2) {
// 数组引用是否相同
if (array1 == array2) {
return true;
}
// 数组大小是否相同
if (array1 == null || array2 == null || array1.length != array2.length) {
return false;
}
// 数组内元素比较
for (int i = 0; i < array1.length; i++) {
Object e1 = array1[i], e2 = array2[i];
if (!(e1 == null ? e2 == null : e1.equals(e2))) {
return false;
}
}
return true;
}
它主要比较了三个方面:
1、两个数组引用是否相同
2、如果引用不同,两个数组长度是否相同
3、如果引用不同,数组长度相同,比较数组元素
public static boolean deepEquals(Object[] array1, Object[] array2) {
if (array1 == array2) {
return true;
}
if (array1 == null || array2 == null || array1.length != array2.length) {
return false;
}
for (int i = 0; i < array1.length; i++) {
Object e1 = array1[i], e2 = array2[i];
if (!deepEqualsElements(e1, e2)) {
return false;
}
}
return true;
}
这个跟上面大致相同,只是在元素比较的时候,它使用了深度比较,具体的实现如下。
private static boolean deepEqualsElements(Object e1, Object e2) {
Class> cl1, cl2;
// 引用是否相同
if (e1 == e2) {
return true;
}
// 是否为空
if (e1 == null || e2 == null) {
return false;
}
// 如果e1或者e2是一个数组,则返回它的元素类型
// 否则,返回null
cl1 = e1.getClass().getComponentType();
cl2 = e2.getClass().getComponentType();
// 元素类型比较
if (cl1 != cl2) {
return false;
}
// 如果e1不是数组,直接进行元素比较
if (cl1 == null) {
return e1.equals(e2);
}
// 如果元素不是原始类型,继续进行数组深度比较
// 因为e1和e2是数组
if (!cl1.isPrimitive()) {
return deepEquals((Object[]) e1, (Object[]) e2);
}
// 如果元素是原始类型,则直接进行比较
if (cl1.equals(int.class)) {
return equals((int[]) e1, (int[]) e2);
}
if (cl1.equals(char.class)) {
return equals((char[]) e1, (char[]) e2);
}
if (cl1.equals(boolean.class)) {
return equals((boolean[]) e1, (boolean[]) e2);
}
if (cl1.equals(byte.class)) {
return equals((byte[]) e1, (byte[]) e2);
}
if (cl1.equals(long.class)) {
return equals((long[]) e1, (long[]) e2);
}
if (cl1.equals(float.class)) {
return equals((float[]) e1, (float[]) e2);
}
if (cl1.equals(double.class)) {
return equals((double[]) e1, (double[]) e2);
}
return equals((short[]) e1, (short[]) e2);
}
3、排序函数
在Arrays的sort函数中,对char、double、float、int、long、short类型的数组进行排序时,它的内部使用的是插入排序和快速排序。
public static void sort(short[] array) {
DualPivotQuicksort.sort(array);
}
public static void sort(int[] a) {
doSort(a, 0, a.length - 1);
}
private static final int INSERTION_SORT_THRESHOLD = 32;
private static void doSort(int[] a, int left, int right) {
// 如果数组长度小于32时,使用插入排序
if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
for (int i = left + 1; i <= right; i++) {
int ai = a[i];
int j;
for (j = i - 1; j >= left && ai < a[j]; j--) {
a[j + 1] = a[j];
}
a[j + 1] = ai;
}
} else { // 否则使用快速排序
dualPivotQuicksort(a, left, right);
}
}
另外这里的快速排序跟我们普通的快速排序有些不同,感兴趣的可以看看源码。
在Arrays的sort函数中,对Object数组排序时,使用的是使用的是二分排序。