在 java 中,使用 iterator 遍历集合时调用集合的 clear() 方法会直接清空集合,并在下一次迭代操作(如 next())时抛出 concurrentmodificationexception。这是因为 clear() 修改了集合的内部结构计数,而 iterator 依赖该计数来检测并发修改。要安全地清空集合,应使用 iterator 提供的 remove() 方法,或者在遍历结束后再调用 clear()。

Iterator 如何检测 clear() 导致的并发修改
Iterator 通过比较集合的 modCount 与自身记录的 expectedModCount 来检测并发修改。当调用 clear() 时,集合内部会将 modCount 增加,但不会更新 Iterator 的 expectedModCount。因此,在下一次调用 next() 或 hasNext() 时,两者不一致,导致异常抛出。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ClearIteratorDemo {
public static void main(String[] args) {
List<string> list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");
Iterator<string> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
System.out.println("Current: " + item);
// 这里调用 clear() 会破坏 Iterator 的状态
if (item.equals("A")) {
list.clear();
}
// 下一次 next() 会抛出 ConcurrentModificationException
if (it.hasNext()) {
System.out.println("Next: " + it.next());
}
}
}
}</string></string>
运行上述代码,输出为:
Current: A
随后抛出 java.util.ConcurrentModificationException。这验证了 clear() 会触发快速失败机制。
使用 remove() 安全清空集合元素
如果需要在遍历过程中移除元素,应使用 Iterator 的 remove() 方法。该方法会同步更新 modCount 和 expectedModCount,避免并发修改异常。若要清空整个集合,可以遍历并逐个移除,或在遍历后调用 clear()。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SafeRemoveDemo {
public static void main(String[] args) {
List<string> list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");
Iterator<string> it = list.iterator();
while (it.hasNext()) {
it.next();
it.remove(); // 安全移除当前元素
}
System.out.println("List size after removal: " + list.size());
}
}</string></string>
运行上述代码,输出为:
List size after removal: 0
集合被安全清空,未抛出异常。这表明 remove() 是遍历中移除元素的正确方式。
clear() 对已获取元素引用的影响
即使 clear() 抛出了异常,之前通过 next() 获取的元素引用仍然有效。例如,在抛出异常前,变量 item 指向堆中的字符串对象,该对象不会被回收。但若后续尝试访问集合状态(如再次调用 next()),则会因状态不一致而失败。因此,异常发生后,程序应捕获异常并处理,避免崩溃。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











