2

ConcurrentModificationException由于我正在迭代一个我正在修改的集合,因此以下模型代码最终以.

Set<String> data = new HashSet<String>();
data.add("a=1");
data.add("b=2");
data.add("c=3");
data.add("d=4");

for (String s : data) {
    data.remove(s);
}

但是为什么会这样呢?请帮忙澄清

4

4 回答 4

2

抛出异常仅仅是因为您data.remove(s)在迭代集合时正在修改集合(通过调用)。Java 集合通常要求在迭代其值时不能修改它们。

官方文档

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

于 2011-08-30T18:50:35.510 回答
2

您违反了迭代器的合同。从ConcurrentModificationExceptionjavadoc

如果单个线程发出一系列违反对象约定的方法调用,则该对象可能会抛出此异常。例如,如果线程在使用快速失败迭代器迭代集合时直接修改了集合,则迭代器将抛出此异常。

于 2011-08-30T18:50:40.463 回答
1

您必须使用 Iterator 从 Set 中删除元素

于 2011-08-30T18:50:19.567 回答
1

这是因为编译器实际上插入了一个Iterator然后使用传统的 for 循环来迭代元素。如果您修改Collection迭代器所基于的,这将导致不确定的行为。为了防止这种情况,ConcurrentModificationException被抛出。

另请参阅此处

第 7 项. 不要在迭代期间修改列表。虽然 for-each 语法不提供对等效基本 for 循环使用的迭代器的直接访问,但可以通过直接调用列表上的其他方法来修改列表。这样做会导致程序行为不确定。特别是,如果编译器插入的对 iterator() 的调用返回一个快速失败的迭代器,则可能会引发 java.util.ConcurrentModificationException 运行时异常。但这只是在尽力而为的基础上完成的,除非作为在抛出异常时检测错误的一种手段,否则不能依赖它。

或语言规范中的 for each 循环部分。

于 2011-08-30T18:55:49.130 回答