有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

清除子列表时的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??

共 (4) 个答案

  1. # 1 楼答案

    ^{}masterList上的视图。只有一个底层集合。现在主列表有点像子列表。所以

    • ^如果删除了masterlist's元素,{}就不可能存在//异常情况
    • ^如果删除sublist's元素,{}可以存在//确定
  2. # 2 楼答案

    根据ArrayList docsubList()返回一个子列表,该子列表由原始ArrayList支持,因此,如果原始ArrayList发生更改,则在执行子列表时,子列表也会随之更改。clear()子列表本身已经不存在了

  3. # 3 楼答案

    SubList不是一个独立的实体,但它只是给出了原始列表的视图,并且在内部引用了同一个列表。因此,它的设计似乎是这样的,如果基础列表在结构上被修改(添加/删除元素),它就无法履行其合同

    here in the source code of SubList所示,方法checkForComodification检查基础列表是否已被修改,因此,如果modCount(列表已被结构修改的次数)的SubList值与父ArrayList不相同,则抛出ConcurrentModificationException

    因此,清除从中创建SubList的父ArrayList可能会导致SubList的某些操作导致ConcurrentModificationException

  4. # 4 楼答案

    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.)

    未定义的语义当然意味着允许它抛出异常(实际上,这可能是最明智的做法)

    因此,您可以更改子列表的大小,并将这些更改反映在主列表中,但情况并非如此