在AbstractCollection的toArray方法的实现中,代码的用法是什么

Cha*_*ong 11 java collections

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;
}
Run Code Online (Sandbox Code Playgroud)

这是AbstractCollection.toArray方法的实现代码.

if (! it.hasNext()) // fewer elements than expected
    return Arrays.copyOf(r, i);
Run Code Online (Sandbox Code Playgroud)

我不明白上面代码的用法.我怀疑代码用于避免在调用方法时更改大小.所以我有两个问题:

  1. 我怀疑是对还是错?如果它错了,这段代码的用法是什么?
  2. 如果这是真的,在调用方法时,什么情况可以改变大小?

Shi*_*gon 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>
     */
Run Code Online (Sandbox Code Playgroud)

我发现这里有两件有趣的事情要提到:

  1. 是的,你是对的,就像javadoc sais一样,这个方法准备好正确地返回,即使集合在同一时间被修改了.这就是为什么初始尺寸只是一个提示.迭代器的使用还确保避免"并发修改"异常.

  2. 很容易想象一个多线程情况,其中一个线程在Collection中添加/删除元素,而另一个线程在其上调用"toArray"方法.在这种情况下,如果Collection不是线程安全的(例如通过Collections.synchronizedCollection(...)方法获得,或者通过手动创建同步访问代码),您将进入同时修改和编译的情况.