public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
这是AbstractCollection.toArray
方法的实施代码。
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
我不明白上面代码的用法。我怀疑代码用于避免在调用方法时更改大小。所以我有两个问题:
答案 0 :(得分:6)
嗯,方法的javadoc就是这样:
/**
* {@inheritDoc}
*
* <p>This implementation returns an array containing all the elements
* returned by this collection's iterator, in the same order, stored in
* consecutive elements of the array, starting with index {@code 0}.
* The length of the returned array is equal to the number of elements
* returned by the iterator, even if the size of this collection changes
* during iteration, as might happen if the collection permits
* concurrent modification during iteration. The {@code size} method is
* called only as an optimization hint; the correct result is returned
* even if the iterator returns a different number of elements.
*
* <p>This method is equivalent to:
*
* <pre> {@code
* List<E> list = new ArrayList<E>(size());
* for (E e : this)
* list.add(e);
* return list.toArray();
* }</pre>
*/
我发现有两件有趣的事情要提到:
是的,你是对的,就像javadoc sais一样,即使Collection同时被修改,这个方法也准备正确返回。这就是为什么初始尺寸只是一个提示。迭代器的使用也确保避免“并发修改”异常。
很容易想象一个多线程情况,其中一个线程在Collection中添加/删除元素,而另一个线程在其上调用“toArray”方法。在这种情况下,如果Collection不是线程安全的(如通过Collections.synchronizedCollection(...)
方法获得,或者通过手动创建同步访问代码),您将进入一个被修改的状态,并在同一时间进行编译时间。
答案 1 :(得分:3)
我只想提一下,根据javadoc,方法size()
可以返回最大的Integer.MAX_VALUE。但是如果你的收藏品有更多的元素,你将无法获得合适的尺寸。
答案 2 :(得分:0)
你是对的,数组是用size()初始化的,所以如果在填充数组时删除了任何元素,你可以从这个检查中受益。
默认情况下,集合不是线程安全的,因此在迭代进行时,另一个线程可以调用remove(): - )
答案 3 :(得分:0)
虽然通常保证(例如对于所有java.util。*集合类)集合在迭代时不会更改(否则会抛出ConcurrentModificationException),但并不能保证所有集合都能保证。因此,当一个线程调用toArray()时,另一个线程可以添加或删除元素,从而改变集合的大小,从而改变结果数组。或者,某些实现可能只返回大致的大小。
因此,回答这个问题:
这两行检查是否在达到预期大小(定义r.length的size()调用的结果)之前到达了集合的结尾。如果是这种情况,将生成具有适当大小的数组r的副本。请记住,无法调整阵列大小。
如上所述,自收集合约以来,不同的可能性相当宽松。多线程,大小()和其他的近似结果。
答案 4 :(得分:0)