-1

如果我使用Iterator.remove(),一切都很好。如果我使用ArryaList.remove(),我总是收到错误java.util.ConcurrentModificationException

谁能指出原因?

4

4 回答 4

4

javadocs 说明了一切:

当这种修改是不允许的时,检测到对象的并发修改的方法可能会抛出此异常。

例如,通常不允许一个线程在另一个线程对其进行迭代时修改 Collection。一般来说,在这些情况下,迭代的结果是不确定的。如果检测到此行为,某些迭代器实现(包括 JRE 提供的所有通用集合实现的那些)可能会选择抛出此异常。这样做的迭代器被称为快速失败迭代器,因为它们快速而干净地失败,而不是在未来不确定的时间冒着任意的、非确定性的行为的风险。

您正在修改一个集合并同时对其进行迭代。

于 2012-06-11T00:22:07.747 回答
2

基本上是因为它就是这样设计的。如果从列表中删除一个元素,迭代器不知道它,当它尝试访问列表中的另一个元素时,列表已更改并引发错误。但是,如果您通过迭代器删除一个元素,那么迭代器就会知道删除,对其数据结构进行适当的调整,然后继续。

于 2012-06-11T00:21:52.463 回答
1

所以完全来自文档

当这种修改是不允许的时,检测到对象的并发修改的方法可能会抛出此异常。

例如,通常不允许一个线程在另一个线程对其进行迭代时修改 Collection。一般来说,在这些情况下,迭代的结果是不确定的。如果检测到此行为,某些迭代器实现(包括 JRE 提供的所有通用集合实现的那些)可能会选择抛出此异常。这样做的迭代器被称为快速失败迭代器,因为它们快速而干净地失败,而不是在未来不确定的时间冒着任意的、非确定性的行为的风险。

看看Class ConcurrentModificationException

于 2012-06-11T00:21:38.763 回答
0

如果在迭代列表时需要删除元素,则应始终使用迭代器。

例如

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 循环在底层使用了迭代器。而且您正在手动从列表中删除元素,而不是通过迭代器。这就是为什么你得到那个例外。

于 2012-06-11T00:43:02.440 回答