Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what's the usage of the code in the implementation of AbstractCollection's toArray Method

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;
}

here's the code of implementation of AbstractCollection.toArray method.

if (! it.hasNext()) // fewer elements than expected
    return Arrays.copyOf(r, i);

I don't understand the usage of the code above. I suspect the code is used to avoid the size changing while the the method is invoked. So I have two questions:

  1. What I suspect is right or wrong? if it's wrong, what's the usage of this code?
  2. If it's true, what situation can make the size changing while the method has been invoked?
like image 759
ChandlerSong Avatar asked Dec 06 '11 14:12

ChandlerSong


People also ask

What is the use of ToArray () in Java?

The toArray() method of ArrayList is used to return an array containing all the elements in ArrayList in the correct order.

How do you use the ToArray method?

The toArray() method is used to get an array which contains all the elements in ArrayList object in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array. If the list fits in the specified array, it is returned therein.

What is ToArray in C#?

ToArray(Type)Copies the elements of the ArrayList to a new array of the specified element type. public: virtual Array ^ ToArray(Type ^ type); C# Copy.


2 Answers

Well, the method's javadoc sais it all:

 /**
     * {@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>
     */

I find two interesting things to mention here:

  1. Yes, you're right, as the javadoc sais, this method is prepared to return correctlly even if the Collection has been modified in the mean time. That's why the initial size is just a hint. The usage of the iterator also ensures avoidance from the "concurrent modification" exception.

  2. It's very easy to imagine a multi-threaded situation where one thread adds/removes elements from a Collection while a different thread calls the "toArray" method on it. In such a situation, if the Collection is not thread safe (like obtained via Collections.synchronizedCollection(...) method, or by manually creating synchronized access code towards it) you'll get into a situation where it's modified and toArray-ed at the same time.

like image 125
Shivan Dragon Avatar answered Nov 15 '22 20:11

Shivan Dragon


I just want to mention that according to the javadoc, the method size() can return maximum Integer.MAX_VALUE. But if your collection has more elements you can't get a proper size.

like image 21
corsair Avatar answered Nov 15 '22 19:11

corsair