1

使用经典 for 循环时是否有可能发生并发修改异常?

import java.util.*;

class IterTest{
    public static void main(String[] args){
        List<Integer> nums = new ArrayList<>();
        nums.add(18);
        nums.add(1);
        nums.add(14);
        nums.add(13);
        System.out.println("Nums ->"+nums);
        int len = nums.size();
        for(int index=0;index < len ;index++){          
            System.out.println(" Current >>"+nums.get(index));
            System.out.println(" Removing >>"+nums.remove(index));          
        }
    }
}
4

3 回答 3

2

不,此代码不会给出ConcurrentModificationException. 当集合的视图被从其下方更改出来的集合“破坏”时,通常会发生该异常。Iterator这方面的典型示例是在通过 a (在增强的 for 语句中隐式使用)或通过获取 a进行迭代时修改集合subList(),修改基础列表,然后继续使用子列表。

但是,此代码将遇到与“破坏”循环相同的情况,除了将引发不同的异常。循环边界基于列表的初始大小。但是,循环体会从列表中删除元素,因此代码最终会在列表边界之外进行索引,从而导致IndexOutOfBoundsException.

如何修复此代码取决于您要执行的操作。通过使用列表索引ConcurrentModificationException而不是Iterator. 但是,如果在循环过程中对列表进行结构修改(即添加或删除元素),则需要仔细调整索引和循环边界,否则可能会跳过、重复或IndexOutOfBoundsException发生元素。

于 2019-02-27T17:32:06.983 回答
2

不,没有机会。使用迭代器时可能会发生并发修改异常,请参阅什么是 java 中的故障安全和故障快速迭代器

于 2019-02-27T06:31:34.690 回答
0

不,正如其他答案所暗示的那样,ConcurrentModificationException在给定的代码中不会出现。

那么 ConcurrentModificationException 什么时候发生呢?

在单线程环境中,当您使用迭代器循环收集并同时修改它时,通常会发生这种情况。

为什么?

如果您检查迭代器实现的源代码,每当您使用迭代器的任何方法(例如 next()、remove())时,它总是会执行 checkForComodification()。例如,ArrayList.java 中该方法的代码是:

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

其中modCount是在 ArrayList 类级别维护的静态变量,表示此列表在结构上被修改的次数。并且预期修改计数expectedModCount维护在 Iterator 类级别,最初等于 modCount。

因此,只要预期的修改数量与实际完成的修改不匹配,就会出现异常。

在您的情况下,您没有使用任何这些,因此不会检查 Co-modification,因此您不会得到 ConcurrentModificationException.

注意:本答案中所述,您将得到,IndexOutOfBoundsException因为您已签index < len入 for 循环并len初始化为数组的初始大小。一个简单的解决方案是:

 for(int index=0;index < nums.size;index++)
于 2019-03-24T14:45:11.733 回答