必须用 Iterator 的 hasNext() 和 next() 搭配 remove() 删除元素,因 for-each 隐式使用 Iterator 但禁用 remove,普通 for 循环删除会导致元素前移而跳过或越界。
要安全、高效地在遍历集合时删除元素,必须用 iterator 的 hasnext() 和 next() 搭配 remove(),不能直接调用集合自身的 remove(),否则会抛 concurrentmodificationexception。
为什么不能用 for-each 或普通 for 循环删元素
for-each 本质是隐式使用 Iterator,但屏蔽了 remove 调用入口;普通 for 循环靠索引操作,删除后元素前移,容易跳过下一个元素或越界。例如:
错误示范:
for (String s : list) {
if (s.equals("bad")) list.remove(s); // 运行时报 ConcurrentModificationException
}
也错误:
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("bad")) list.remove(i); // i 会跳位,且 size 动态变,易漏删或越界
}
标准迭代删除流水线三步写法
核心是:先 hasNext() 判断有无下一项 → 再 next() 取出当前项 → 最后根据条件决定是否 iterator.remove()。
- 每次循环只调一次
next(),避免重复取值或跳过元素 -
remove()必须紧跟在对应next()之后,且只能调一次(否则抛IllegalStateException) - 不依赖索引,与底层数据结构(ArrayList/LinkedList)无关,通用性强
实战代码模板(以 ArrayList 为例)
以下为可直接复用的删除骨架:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String item = it.next(); // 取出当前元素
if ("bad".equals(item)) { // 判断删除条件
it.remove(); // 安全删除,仅此一处调用
}
}
若需同时处理多个字段或复杂逻辑,可把判断封装成方法:
while (it.hasNext()) {
User user = it.next();
if (shouldRemove(user)) {
it.remove();
}
}
进阶注意点:ListIterator 与并发场景
如果需要双向遍历或在遍历时添加元素,可用 ListIterator,它支持 add()、previous() 等操作。
但在多线程环境下,即使用了 Iterator,原始集合仍非线程安全。此时应:
- 用
Collections.synchronizedList()包装,再手动加锁遍历 - 或改用
CopyOnWriteArrayList,它的 Iterator 是快照式的,遍历时删元素不会报错(但删的是原集合,不影响当前迭代)
不复杂但容易忽略

















