使用经典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));
}
}
}
答案 0 :(得分:2)
不,没有机会。使用迭代器时可能会发生并发修改异常,请参见What are fail-safe and fail-fast iterators in java
答案 1 :(得分:2)
否,此代码不会给出ConcurrentModificationException
。当集合视图从其下面更改而“破坏”集合视图时,通常会发生该异常。典型的示例是在Iterator
(在for-for语句中隐式使用)进行迭代的同时修改集合,或者通过获取subList()
,修改基础列表,然后继续使用子列表。
但是,此代码将以与“欺骗”循环相同的条件运行,只是会引发不同的异常。循环边界基于列表的初始大小。但是,循环体从列表中删除了元素,因此代码最终将在列表的边界之外建立索引,从而产生IndexOutOfBoundsException
。
如何修复此代码取决于您要执行的操作。最初似乎最好通过使用列表索引而不是ConcurrentModificationException
来避免使用Iterator
。但是,如果在循环过程中对列表进行结构上的修改(即添加或删除了元素),则需要仔细调整索引和循环边界,否则可能会跳过,重复元素或发生IndexOutOfBoundsException
答案 2 :(得分:0)
否,正如其他答案所建议的那样,在给定的代码中不会出现ConcurrentModificationException
。
在单线程环境中,通常会在使用Iterators遍历集合并同时对其进行修改时发生。
如果您检查Iterator实现的源代码,则无论何时使用iterator的任何方法(例如next(),remove()),它始终会执行checkForComodification()。例如,在ArrayList.java中该方法的代码为:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
其中 modCount 是在ArrayList类级别维护的静态变量,表示该列表在结构上被修改的次数。 预期的修改计数 expectedModCount ,在Iterator类级别上维护,该级别最初等于modCount。
因此,只要预期的修改数量与实际进行的修改不匹配,就会出现异常。
在您的情况下,您没有使用过任何一种,因此不会检查共同修改,因此您将不会获得ConcurrentModificationException
。
注意:
如this answer中所述,由于在for循环中检查了IndexOutOfBoundsException
,并且index < len
被初始化为数组的初始大小,您将得到len
。
一个简单的解决方案是:
for(int index=0;index < nums.size;index++)