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.