Why does the following code throw ConcurrentModificationExcrption
, when I clear the sub List after the master List, but not if I clear the sub list and then the master List?
ArrayList<Integer> masterList = new ArrayList<Integer>();
List<Integer> subList;
// Add some values to the masterList
for (int i = 0; i < 10; i++) {
masterList.add(i * i);
}
// Extract a subList from the masterList
subList = masterList.subList(5, masterList.size() - 1);
// The below throws ConcurrentModificationException
masterList.clear();
subList.clear(); // Exception thrown in this line
// The below doesn't throw any exception
subList.clear();
masterList.clear(); // No exception thrown. Confused??
SubList
is not an independent entity, but it is just giving a view of the original list, and internally refers to same list. Hence, its design seem to be such that if underlying list is modified structurally (addition/removal of elements), it is not able to fulfill its contract.
As can be seen here in the source code of SubList, the method checkForComodification
checks whether the underlying list has been modified, and thus if the modCount
(number of times the list has been structurally modified) value of SubList
is not same as parent ArrayList
, then, it throws ConcurrentModificationException
So, clearing parent ArrayList
from which SubList
was created can result in the certain operations of SubList
to result in ConcurrentModificationException
subList
is a view over the masterList
. There is just 1 underlying collection. Now masterList is kind of a superset
of sublist. So,
sublist
cannot exist if masterlist's
elements are removed //exception casemasterlist
can exist if sublist's
elements are removed //OKacording to ArrayList doc subList()
returns a sublist that is backed by the original ArrayList, so if the original changes so does the subList, when you execute subList.clear() the sublist itself doesn't exist anymore.
From the API docs:
The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list. (Structural modifications are those that change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.)
Undefined semantics means of course that it is allowed to throw an exception (and indeed this is probably the wisest course of action).
So you can change the size of the sublist and have those changes reflected in the main list, but the reverse isn't true.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With