如果我使用Iterator.remove()
,一切都很好。如果我使用 ArryaList.remove()
,我总是收到错误java.util.ConcurrentModificationException
。
谁能指出原因?
javadocs 说明了一切:
已检测到并发的方法可能会引发此异常 不允许修改对象时进行修改。
例如,通常不允许一个线程修改 一个集合,而另一个线程正在迭代它。通常 在这些情况下,迭代的结果是未定义的。 一些迭代器实现(包括所有通用的 JRE 提供的目的集合实现)可以选择 如果检测到此行为,则引发此异常。执行的迭代器 这被称为快速失败迭代器,因为它们快速失败并且 干净利落,而不是冒着任意的、非确定性行为的风险 未来未定时间。
您正在修改集合并同时循环访问它。
基本上是因为这就是它的设计方式。如果从列表中删除某个元素,迭代器将不知道该元素,并且当它尝试访问列表中的另一个元素时,列表已更改并引发错误。但是,如果您通过迭代器删除元素,则迭代器知道删除,对其数据结构进行适当的调整,然后继续。
所以完全来自文档
已检测到并发的方法可能会引发此异常 不允许修改对象时进行修改。
例如,通常不允许一个线程修改 一个集合,而另一个线程正在迭代它。通常 在这些情况下,迭代的结果是未定义的。 一些迭代器实现(包括所有通用的 JRE 提供的目的集合实现)可以选择 如果检测到此行为,则引发此异常。执行的迭代器 这被称为快速失败迭代器,因为它们快速失败并且 干净利落,而不是冒着任意的、非确定性行为的风险 未来未定时间。
看看类并发修改异常
循环访问列表时删除元素,则应始终使用迭代器。
例如
List<String> list = //...
//...
Iterator<String> iter = list.iterator();
while(iter.hasNext()) {
String str = itr.next();
//...
if(/* ... */) {
iter.remove(str);
}
}
这是在循环访问列表时从列表中删除元素的最安全方法。
注意:您不应执行以下操作:
List<String> list = //...
//...
for(String str : list) {
if(/* ... */) {
list.remove(); // <-- should not do this
}
}
大多数情况下,您最终会陷入ConcurrentModificationException
.增强的 for 循环使用引擎盖下的迭代器。您正在手动从列表中删除元素,而不是通过迭代器。这就是你得到这个例外的原因。