Java中的数组工具类Arrays

Arrays就是Java中的数组工具类,它包含了很多静态的方法来对数组进行操作。

下面我们来看看它对数组可以进行哪些操作。

1、将数组转换成一个List

public static <T> List<T> asList(T... array) {
    return new ArrayList<T>(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> 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> 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数组排序时,使用的是使用的是二分排序。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值