前言
最近在开发过程中遇到一个异常抛出,不能在for循环中对集合元素进行删除,小记一下这个方法!
🔍 一、什么是 Iterator?
Iterator 是 专门用于遍历集合(List / Set)并允许在遍历中安全删除元素的接口 。它是 Java Collection 框架的重要成员,避免 foreach 删除时报 ConcurrentModificationException。
支持的集合:
| 集合类型 |
是否支持 Iterator |
| List |
✔ |
| Set |
✔ |
| Map |
❌(需要转 entrySet) |
|
|
📌 二、Iterator 的核心方法
| 方法 |
作用 |
hasNext() |
是否还有下一个元素 |
next() |
取出下一个元素 |
remove() |
删除当前元素(只能在 next() 后调用) |
|
|
🚀 三、最常用的迭代器遍历写法(标准写法)
Iterator<Long> iterator = ids.iterator();
while (iterator.hasNext()) {
Long id = iterator.next();
System.out.println(id);
}
🧹 四、遍历中安全删除元素(必须使用 iterator.remove())
Iterator<Long> iterator = ids.iterator();
while (iterator.hasNext()) {
Long id = iterator.next();
if (id < 10) {
iterator.remove(); // ❗必须使用 iterator.remove()
}
}
❌ 五、错误写法(一定会报错)
for (Long id : ids) {
ids.remove(id); // ❌ ConcurrentModificationException
}
🔁 六、遍历 Set 集合
Set<String> names = new HashSet<>();
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println(name);
}
🔑 七、遍历 Map(需要转换为 entrySet)
Map<Long, String> map = new HashMap<>();
Iterator<Map.Entry<Long, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Long, String> entry = iterator.next();
System.out.println("key=" + entry.getKey() + ", value=" + entry.getValue());
}
✨ 八、增强版写法:统计 + 删除 + 记录日志
List<Long> removedIds = new ArrayList<>();
Iterator<Long> iterator = ids.iterator();
while (iterator.hasNext()) {
Long id = iterator.next();
if (!filesMapper.isExist(id)) {
removedIds.add(id);
iterator.remove();
}
}
log.info("共删除 {} 个无效 ID:{}", removedIds.size(), removedIds);
📚 九、Iterator vs forEach vs Stream
| 遍历方式 |
是否能删除 |
是否推荐 |
| for-each |
❌ |
不推荐删除 |
| Iterator |
✔ |
CRUD 通用推荐 |
| removeIf |
✔ |
JDK8 最简洁 |
| Stream |
❌ |
可过滤但不可直接删除 |
|
|
|
🌟 十、JDK8 更推荐:removeIf
ids.removeIf(id -> !filesMapper.isExist(id));
📌 十一、Iterator 常见错误总结
| 错误写法 |
后果 |
ids.remove(id) |
报 ConcurrentModificationException |
iterator.remove() 但没有 next() |
IllegalStateException |
用了两次 remove() |
IllegalStateException |
| 修改集合长度时继续遍历 |
逻辑错误 |
|
|
✔ 十二、Iterator 使用场景总结
| 使用场景 |
是否适合用 Iterator |
| 安全删除集合元素 |
✔ 必须 |
| 简单遍历 |
可用,但 forEach 更快 |
| 大量数据遍历 |
✔ |
| 删除元素并记录日志 |
✔ |
| Map 遍历 |
✔(需 entrySet) |
| Stream 操作 |
❌ 不能直接删除 |
|
|
🎯 总结一句话
👉 Iterator 是遍历集合并安全删除元素的唯一方式(forEach ×)。