toArray和toArray(T[])的不同

前言

Collection接口有两个方法Object[] toArray();<T> T[] toArray(T[] a);, 可以用来将集合转为数组。

使用

一个返回Object[], 一个返回T[], 为了避免发生强制转化, 我们一般都是使用<T> T[] toArray(T[] a);
<T> T[] toArray(T[] a);传入的数组大小可以直接填0, 当然也可以直接填source.size()
但是arrays-wisdom-ancients这篇文章做了分析, JDK6以后直接填0性能更好。

1
2
3
4
5
List<String> source = new LinkedList<String>();
// 填充数据
String[] array1 = (Object[]) source.toArray();
String[] array2 = source.toArray(new String[0]);
String[] array3 = source.toArray(new String[source.size()]);

查看ArrayList的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
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;
}
}
public class Arrays {
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.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;
}
}

当我们调用ArrayList.toArray方法的时候, 都会调用Arrays.copyOf方法, 最终调用System.arraycopy方法, 这是一个native方法。
当然, 不同的集合有不同的toArray实现方法。

总结

如果传入的参数toArray(T[] a)小于本身的长度, 会new或者反射创建一个新的数组, 然后将元素复制进去。
但是arrays-wisdom-ancients这篇文章做了分析, JDK6以后直接填0性能更好。