如果我使用Iterator.remove()
,一切都很好。如果我使用ArryaList.remove()
,我总会收到错误java.util.ConcurrentModificationException
。
有谁可以指出原因?
答案 0 :(得分:4)
javadocs说了一切:
检测到并发的方法可能抛出此异常 在不允许进行此类修改时修改对象。
例如,一个线程通常不允许修改 一个集合,而另一个线程正在迭代它。一般来说, 在这些情况下,迭代的结果是不确定的。 一些迭代器实现(包括所有通用的实现) 由JRE提供的目的集合实现可以选择 如果检测到此行为,则抛出此异常。那个迭代器 这被称为故障快速迭代器,因为它们很快就会失败 干净利落,而不是冒着任意的,非确定性的行为冒险 未来不确定的时间。
你正在修改一个集合并同时迭代它。
答案 1 :(得分:2)
基本上因为它是如何设计的。如果从列表中删除元素,则迭代器不知道它,当它尝试访问列表中的另一个元素时,列表已更改并引发错误。但是如果通过迭代器删除一个元素,那么迭代器就会知道删除,对其数据结构进行适当的调整,然后继续。
答案 2 :(得分:1)
完全来自docs
检测到并发的方法可能抛出此异常 在不允许进行此类修改时修改对象。
例如,一个线程通常不允许修改 一个集合,而另一个线程正在迭代它。一般来说, 在这些情况下,迭代的结果是不确定的。 一些迭代器实现(包括所有通用的实现) 由JRE提供的目的集合实现可以选择 如果检测到此行为,则抛出此异常。那个迭代器 这被称为故障快速迭代器,因为它们很快就会失败 干净利落,而不是冒着任意的,非确定性的行为冒险 未来不确定的时间。
答案 3 :(得分:0)
如果在迭代列表时需要删除元素,则应始终使用迭代器。
e.g。
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循环使用了引擎盖下的迭代器。并且您手动从列表中删除元素而不是通过迭代器。这就是你得到这个例外的原因。