Why does List.addAll of a reversed subList of the list cause a ConcurrentModificationException

List.subList returns a live view of the list between the specified elements, not a copy of those elements (see documentation), therefore adding to the original list will also modify the sublist, which will lead to ConcurrentModificationException (since what is being added and to what you add to also are modified at the same time).

list.subList(startIndex, endIndex+1)

You can fix a code by copying the list, like

List<Integer> toReverse = new ArrayList<>(list.subList(startIndex, endIndex+1));

from the documentation of ArrayList.subList :

The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa

So when you try to add items at the index of the subList 'view', it creates concurrent modification.


Issue lies here at ArrayList#checkForComodification

private void checkForComodification() {
    if (ArrayList.this.modCount != this.modCount)
        throw new ConcurrentModificationException();
    }
}

However in this particular case you don't need to manually re-add reversed sublist, since the reversion is performed on the original list. So all you need is just to drop

list.removeAll(...);
list.addAll(...);

and leave only this code:

List<Integer> toReverse = list.subList(startIndex, endIndex+1);
Collections.reverse(toReverse);