清除子列表时出现ConcurrentModificationException
为什么以下代码抛出ConcurrentModificationExcrption
,当我清除主列表后的子列表时,但是如果我清除子列表然后清除主列表则不行?
ArrayList masterList = new ArrayList(); List 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
不是一个独立的实体,但它只是给出原始列表的视图,并在内部引用相同的列表。 因此,它的设计似乎是这样的,如果基础列表在结构上被修改(添加/删除元素),它就无法履行其合同。
从SubList的源代码中可以看出,方法checkForComodification
检查底层列表是否已被修改,因此如果modCount
(列表已被结构修改的次数) SubList
值与父ArrayList
,然后,它抛出ConcurrentModificationException
因此,清除创建SubList
父ArrayList
会导致SubList
的某些操作导致ConcurrentModificationException
subList
是subList
的视图。 只有一个基础集合。 现在masterList是子列表的superset
。 所以,
- 如果删除
masterlist's
元素,则sublist
不存在//exception情况 - 如果删除
sublist's
元素,则可以存在masterlist
// OK
根据ArrayList doc subList()
返回一个由原始ArrayList支持的子列表,因此如果原始更改subList,则当您执行subList.clear()时,子列表本身不再存在。
来自API文档 :
如果支持列表(即此列表)在结构上以除返回列表之外的任何方式进行修改 ,则此方法返回的列表的语义将变为未定义。 (结构修改是那些改变了这个列表的大小,或以其他方式扰乱它的方式,正在进行的迭代可能会产生不正确的结果。)
未定义的语义当然意味着它允许抛出exception(事实上这可能是最明智的行动)。
因此,您可以更改子列表的大小,并将这些更改反映在主列表中,但反之则不然。