当我运行以下代码时,Java正在抛出ConcurrentModificationException
。知道为什么会这样吗?
ArrayList<String> list1 = new ArrayList<String>();
list1.add("Hello");
list1.add("World");
list1.add("Good Evening");
for (String s : list1){
list1.remove(2);
System.out.println(s);
}
答案 0 :(得分:0)
如果您查看ConcurrentModificationException的文档,您会发现
检测到并发的方法可能抛出此异常 在不允许进行此类修改时修改对象。
例如,一个线程通常不允许修改 一个集合,而另一个线程迭代它
...
请注意,此异常并不总是表示对象具有 由另一个线程同时修改。如果是单线程 发出一系列违反合同的方法调用 一个对象,该对象可能抛出此异常。 例如,如果是 线程在迭代时直接修改集合 使用失败快速迭代器进行集合,迭代器将抛出此异常 例外强>
关于此异常的重要一点是,我们无法保证它将始终按照文档
中的说明抛出请注意,通常情况下无法保证快速失败的行为 说话,在场的情况下不可能做出任何硬性保证 不同步的并发修改。 失败操作抛出 尽最大努力
ConcurrentModificationException
。
同样来自ArrayList文档
此类
iterator
和listIterator
返回的迭代器 方法是 失败快速:如果列表在结构上被修改了 创建迭代器之后的时间,除了通过之外的任何方式 迭代器自己删除或添加方法,迭代器会抛出一个ConcurrentModificationException
强>
(强调我的)
所以你不能操纵Collection的内容(在你的情况下是List),同时通过增强的for循环遍历它,因为你没有通过iterator来做 - 每个都在内部使用。
要解决它,只需获得自己的Iterator
并在循环中使用它。要从集合中删除元素,请使用此示例中的remove
Iterator<String> it = list1.iterator();
int i=0;
while(it.hasNext()){
String s = it.next();
i++;
if (i==2){
it.remove();
System.out.println("removed: "+ s);
}
}
答案 1 :(得分:0)
在迭代项目时,您无法删除该项目。如果要在迭代时也删除项目,请使用Iterator
。
但您要删除基于索引的项目,然后只需在循环外移动就行可以解决您的问题。
list1.remove(2);
答案 2 :(得分:0)
形成您可以阅读的doc
检测到并发的方法可能抛出此异常 当不允许这种修改时修改对象。 例如,一个线程通常不允许修改 一个集合,而另一个线程正在迭代它。一般来说, 在这些情况下,迭代的结果是不确定的。 一些迭代器实现(包括所有通用的实现) 由JRE提供的目的集合实现可以选择 如果检测到此行为,则抛出此异常。那个迭代器 这被称为故障快速迭代器,因为它们很快就会失败 干净利落,而不是冒着任意的,非确定性的行为冒险 未来不确定的时间。
此外,假设您可以在每次迭代时删除第2项。您将最终进入索引超出范围的异常:
"Good evening"
),列表大小变为1(项目0 "hello"
和项目1 "World"
)答案 3 :(得分:0)
在修改基础列表后,您无法遍历列表。如果您这样做,它会给您ConcurrentModificationException
要解决此问题,请使用java.util.ListIterator
进行列表迭代。
ListIterator<String> it = list1.listIterator();
for (String s : list1) {
if (it.hasNext()) {
String item = it.next();
System.out.println(item);
}
}