什么传递给Arrays实例方法toArray(T [] a)方法?

时间:2009-04-07 21:17:10

标签: java arrays collections casting

如果你有一个Collection的实例,请说:

Collection<String> addresses = new ArrayList<String>();

然后用一堆值来填充,这是“最好的”方式,如果有的话,使用toArray()方法而不需要类型转换?

String[] addressesArray = addresses.toArray(new String[] {});
String[] addressesArray = addresses.toArray(new String[0]);
String[] addressesArray = addresses.toArray(new String[addresses.size()]);
String[] addressesArray = addresses.toArray(new String[addresses.size() + 5]);

前两个之间是否存在语义差异?第三是最有效的吗?第四个效率低于第三个吗?

6 个答案:

答案 0 :(得分:7)

我的钱

String[] addressesArray = addresses.toArray(new String[0]);

最简单,最不容易出错,因此“最好”。它还具有以下优点:相同的代码适用于并发/同步集合。您必须使用一些非常低级别,使用频繁的代码才能获得可忽略的性能差异,从而产生任何差异。

通常您会看到一个分配给static final的空数组,以避免在每次执行时分配。显然,事实证明,由于“优化”(分配确实非常快),性能可能会下降。

更新:结果显示这比使用大小的数组要快。 http://shipilev.net/blog/2016/arrays-wisdom-ancients/ tl; dr:反射很简单,不涉及慢速方法查找,如果可以确定所有元素都将被写入,则可以删除数组的归零(或阵列变得无法访问)。

答案 1 :(得分:5)

根据a findbugs report,这是最有效的:

String[] addressesArray = addresses.toArray(new String[addresses.size()]);

我相信他们;)

答案 2 :(得分:2)

如果您选择不相信他人,或者只是想自己检查,您可以查看source for java.util.ArrayList(发布来源可能违反某些许可证,我很高兴我只是链接到它)。下载Sun's JDK时,您还会获得所有源代码的副本。

在审核<T> T[] toArray(T[] a);的源代码后,很明显:

String[] addressesArray = addresses.toArray(new String[addresses.size()]);

是最快的方法。

显然,你不能总是花时间阅读和理解源代码,有时候表现最佳的选项并不总是很明显,但对于更简单的方法,阅读源代码可能非常有用。

答案 3 :(得分:1)

这主要是理论上的兴趣,但如果列表经常为空,则可以重用零长度数组:

private static final String[] EMPTY_STRING_ARRAY = {};
...
String[] addressesArray = addresses.toArray(EMPTY_STRING_ARRAY);

由于零长度数组是不可变的(与非零长度数组不同),因此可以存储和重用它们。

答案 4 :(得分:0)

这在List接口的javadoc中有记录:

  

如果列表适合指定的数组,并且有空余空间(即,数组的元素多于列表),则紧跟在列表末尾的数组中的元素将设置为null。 (仅当调用者知道列表不包含任何null元素时,这在确定列表长度时很有用。)

答案 5 :(得分:0)

你在前两个陈述中做了同样的事情。

第三个是效率最高的,因为如果你的元素不适合数组,就会为你创建一个新数组。