【问题标题】:Java concurrent modification exception is not coming while using collections remove method使用集合删除方法时不会出现Java并发修改异常
【发布时间】:2017-09-24 13:42:36
【问题描述】:

我在很多地方都看到,在迭代时从 ArrayList 中删除元素时,我应该使用迭代器删除方法而不是集合删除方法以避免并发修改异常。

但是,下面的代码使用 Java 1.8 Collection remove 可以正常工作,而不会给出并发修改异常。可以看到我这里没有使用迭代器来移除对象。

List<MyObject> list = new ArrayList<MyObject>();
list.add(new MyObject());
list.add(new MyObject());
list.add(new MyObject());

for (int i=0; i<list.size(); i++) {
        list.remove(i);     
}

【问题讨论】:

  • 并发修改异常是在尽力而为的基础上抛出的,你的程序不能总是期望它在发生时抛出
  • 你是幸运的,或者实际上是不幸的......你决定。
  • 你为什么认为ConcurrentModificationException会被抛出?
  • 如果您想知道为什么它没有做您期望的事情,请检查您正在调用的所有方法的 Javadoc。

标签: java arraylist collections concurrentmodification


【解决方案1】:

您的示例不会引发异常。 不过,它也不会从列表中删除所有元素。

真正的作用

  • 在第一次迭代时,它会删除索引 0;列表中还有 2 个元素
  • 在第二次迭代时,它会删除索引 1(实际上是最后一个元素);剩余 1 个元素
  • 不会发生第三次迭代,因为到那时 list.size() 是 1,小于 2

起初,我以为它会抛出 IndexOutOfBoundsException,但事实上 list.size() 在每次迭代开始时都会被评估,这确保它不会。

为什么不抛出 ConcurrentModificationException

因为你没有使用迭代器。

如果您使用迭代器迭代列表,然后修改(例如删除)列表,然后尝试推进迭代器,则会引发此异常,如下所示:

Iterator<MyObject> it = list.iterator();
while (it.hasNext()) {
    list.remove(it.next());
}

正如@Ferrybig 指出的那样,即使在这种情况下,迭代器实际上也可能不会抛出异常 - 请参阅related question

【讨论】:

    猜你喜欢
    • 2014-06-24
    • 2014-07-12
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多