JAVA-DIY-10-WEEK

Persistence is not necessarily successful, but not sure will not succeed.

Posted by Hyuga on May 26, 2019

第10次讨论主题:集合转数组

ArrayList.toArray()推荐有参数,还是无参数,为什么?

推荐有参数的public <T> T[] toArray(T[] a)

ArrayList<Integer> arrayList = new ArrayList<>();

Object[] objects = arrayList.toArray();

Integer[] integers = arrayList.toArray(new Integer[2]);

单从返回结果看,无参返回的是Object[],如果只是拿来打印输出的话倒也没什么所谓,但如果是要对返回结果进行操作,则需要进行类型转换,手动类型转换,可能出现类型转换异常问题。从这一点考虑,有参返回更安全。

详解

  • Arrays.copyOf(elementData, size);
  • (T[]) Arrays.copyOf(elementData, size, a.getClass());

其实都是调用了以下方法!

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

copyOf方法创建了一个新的T[]数组,类型为原集合类型或参数数组类型,在调用System.arraycopy进行拷贝。 无参方法直接根据原集合类型创建一个新的Object[]对象调用System.arraycopy进行拷贝。 有参方法根据参数数组类型,通过数组反射生成一个新的T[]数组对象调用System.arraycopy进行拷贝。

当使用有参方法时,如果参数数组类型和最终接收的数组类型不同,会报编译错误。

如下代码:

ArrayList<Integer> arrayList = new ArrayList<>();
Integer[] integers = arrayList.toArray(new String[0]);

如果有参数,那么参数的数组长度是多少?给出分析的逻辑思考。

源码:

public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}
public <T> T[] toArray(T[] a) {
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

有参方法其实比无参方法多了一些判断,当有参方法的数组参数长度小于原集合的size时,其实也是同无参方法一样执行Arrays.copyOf(elementData, size);

区别在于,当a.length >= size时,直接执行System.arraycopy()方法进行数组拷贝,拷贝后直接返回参数数组,如果参数数组长度比原集合size大,则用null补齐元素。

最好的参数数组长度是等于原集合size.直接把原集合元素拷贝到参数数组中。