While Collections.shuffle() doesn't throw ConcurrentModificationException

I'm actually learning collections and exceptions and I can't understand why this works :

List<Integer> intList = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
for (Integer s : intList) {
     Collections.shuffle(intList);
     System.out.println(s);
 }

Reading the documentation, it states

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

Looking at the source code of Collections :

public static void shuffle(List<?> list) {
        if (r == null) {
            r = new Random();
        }
        shuffle(list, r);
}

So I take a look at the shuffle function :

public static void shuffle(List<?> list, Random rnd) {
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i=size; i>1; i--)
                swap(list, i-1, rnd.nextInt(i));
        } else {
            Object arr[] = list.toArray();

            // Shuffle array
            for (int i=size; i>1; i--)
                swap(arr, i-1, rnd.nextInt(i));

            // Dump array back into list
            ListIterator it = list.listIterator();
            for (int i=0; i<arr.length; i++) {
                it.next();
                it.set(arr[i]);
            }
        }
    }

Finally it calls the swap function :

public static void swap(List<?> list, int i, int j) {
        final List l = list;
        l.set(i, l.set(j, l.get(i)));
}

Does not this modify the current list while iterating on it (or this is because of this line final List l = list;) ? I think I'm missing something important.

Jon Skeet
people
quotationmark

The answer lies in the documentation - emphasis mine:

(A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.)

...

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

shuffle only calls set, therefore it's not performing a structural modification, therefore the iterator doesn't throw an exception.

people

See more on this question at Stackoverflow