清除子列表时的java ConcurrentModificationException
当我清除主列表之后的子列表时,为什么下面的代码会抛出ConcurrentModificationExcrption
,但如果我先清除子列表,然后再清除主列表,则不会抛出ConcurrentModificationExcrption
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??
# 1 楼答案
^{} 是
masterList
上的视图。只有一个底层集合。现在主列表有点像子列表。所以masterlist's
元素,{sublist's
元素,{# 2 楼答案
根据ArrayList doc
subList()
返回一个子列表,该子列表由原始ArrayList支持,因此,如果原始ArrayList发生更改,则在执行子列表时,子列表也会随之更改。clear()子列表本身已经不存在了# 3 楼答案
SubList
不是一个独立的实体,但它只是给出了原始列表的视图,并且在内部引用了同一个列表。因此,它的设计似乎是这样的,如果基础列表在结构上被修改(添加/删除元素),它就无法履行其合同如here in the source code of SubList所示,方法
checkForComodification
检查基础列表是否已被修改,因此,如果modCount
(列表已被结构修改的次数)的SubList
值与父ArrayList
不相同,则抛出ConcurrentModificationException
因此,清除从中创建
SubList
的父ArrayList
可能会导致SubList
的某些操作导致ConcurrentModificationException# 4 楼答案
从the API docs
未定义的语义当然意味着允许它抛出异常(实际上,这可能是最明智的做法)
因此,您可以更改子列表的大小,并将这些更改反映在主列表中,但情况并非如此