ArrayList(Collection<? extends E> c) thread safe? ArrayList(Collection<? extends E> c) thread safe? multithreading multithreading

ArrayList(Collection<? extends E> c) thread safe?


Hint: as @John Bollinger justly mentioned, particular ArrayList implementation is not covered by language specification. So written below is true for Oracle java 8 implementation.


Yes, it is safe if source is synchronised collection, because ArrayList constructor in this case uses toArray() method of source collection, which is synchronised as well and produce new copy of data:

public ArrayList(Collection<? extends E> c) {    elementData = c.toArray();    // ...}


The answer to your specific question is the answer to the question - is the source collection thread safe?

The best way to go about trying to understand how we get there, we can go to the source.

Starting with ArrayList

public ArrayList(Collection<? extends E> c) {    elementData = c.toArray();        size = elementData.length;        // c.toArray might (incorrectly) not return Object[] (see 6260652)        if (elementData.getClass() != Object[].class)            elementData = Arrays.copyOf(elementData, size, Object[].class);    }

Diving into the documentation for Collection.toArray

/** * Returns an array containing all of the elements in this collection. * If this collection makes any guarantees as to what order its elements * are returned by its iterator, this method must return the elements in * the same order. * * <p>The returned array will be "safe" in that no references to it are * maintained by this collection.  (In other words, this method must * allocate a new array even if this collection is backed by an array). * The caller is thus free to modify the returned array. * * <p>This method acts as bridge between array-based and collection-based * APIs. * * @return an array containing all of the elements in this collection */Object[] toArray();

Back to ArrayList.toArray (Assuming the source collections runtime type is an ArrayList)

/** * Returns an array containing all of the elements in this list * in proper sequence (from first to last element). * * <p>The returned array will be "safe" in that no references to it are * maintained by this list.  (In other words, this method must allocate * a new array).  The caller is thus free to modify the returned array. * * <p>This method acts as bridge between array-based and collection-based * APIs. * * @return an array containing all of the elements in this list in *         proper sequence */public Object[] toArray() {    return Arrays.copyOf(elementData, size);}

and finally onto Array.copyOf

/** * Copies the specified array, truncating or padding with nulls (if necessary) * so the copy has the specified length.  For all indices that are * valid in both the original array and the copy, the two arrays will * contain identical values.  For any indices that are valid in the * copy but not the original, the copy will contain <tt>null</tt>. * Such indices will exist if and only if the specified length * is greater than that of the original array. * The resulting array is of the class <tt>newType</tt>. * * @param <U> the class of the objects in the original array * @param <T> the class of the objects in the returned array * @param original the array to be copied * @param newLength the length of the copy to be returned * @param newType the class of the copy to be returned * @return a copy of the original array, truncated or padded with nulls *     to obtain the specified length * @throws NegativeArraySizeException if <tt>newLength</tt> is negative * @throws NullPointerException if <tt>original</tt> is null * @throws ArrayStoreException if an element copied from *     <tt>original</tt> is not of a runtime type that can be stored in *     an array of class <tt>newType</tt> * @since 1.6 */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;}

System.arraycopy is a native method. The call to c.toArray at the top of its invocation stack uses System.arraycopy which is a native method which isn't documented to be thread safe.

Moving back down the stack, the answer to your specific question is the answer to the question - is the source collection thread safe?

If you are using an ArrayList as the source collection, you will need to ensure thread safety in your code.