在java中遍历hashset时删除元素需避免concurrentmodificationexception:1. 推荐用iterator.remove();2. 可先收集待删元素再批量removeall();3. java 8+推荐用removeif()。

在 Java 中直接在遍历 HashSet 时调用 set.remove() 会抛出 ConcurrentModificationException(并发修改异常),因为普通增强 for 循环或迭代器隐式使用的是“快速失败”(fail-fast)机制,不允许遍历过程中结构被修改(除非通过迭代器自身的 remove() 方法)。
使用 Iterator 的 remove() 方法(推荐)
这是最安全、最标准的做法。必须通过迭代器的 remove() 方法删除当前元素,不能用集合本身的 remove()。
- 先获取
Iterator对象 - 在
while (it.hasNext())循环中调用it.next()获取元素 - 满足条件时,立即调用
it.remove()
示例:
HashSet<string> set = new HashSet(Arrays.asList("a", "b", "c", "d"));
Iterator<string> it = set.iterator();
while (it.hasNext()) {
String s = it.next();
if ("b".equals(s) || "c".equals(s)) {
it.remove(); // ✅ 正确:用迭代器删除
}
}
// set 现在为 ["a", "d"]
</string></string>
收集待删元素,遍历结束后批量删除
如果逻辑较复杂,或需要多次判断再统一清理,可先用另一个集合暂存要删除的元素,遍历完再调用 removeAll()。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 避免在遍历时修改原集合,完全规避异常
- 适合删除条件分散、或需跨多轮判断的场景
- 注意内存开销:临时集合会额外占用空间
示例:
HashSet<string> set = new HashSet(Arrays.asList("a", "b", "c", "d"));
Set<string> toRemove = new HashSet();
for (String s : set) {
if (s.length() == 1 && s.charAt(0) >= 'b') {
toRemove.add(s);
}
}
set.removeAll(toRemove); // ✅ 安全删除
</string></string>
使用 removeIf()(Java 8+,简洁高效)
Collection.removeIf(Predicate) 是专为条件删除设计的 API,内部已处理迭代安全问题,代码最简,语义最清晰。
- 一行解决,无需手动管理迭代器
- 底层仍基于迭代器,但封装了安全逻辑
- 适用于单条件或 Lambda 表达式能表达的逻辑
示例:
HashSet<string> set = new HashSet(Arrays.asList("a", "b", "c", "d"));
set.removeIf(s -> "b".equals(s) || "c".equals(s)); // ✅ 简洁安全
</string>
不推荐的方式:转数组或 Stream 过滤重建
例如 set = new HashSet(set.stream().filter(...).collect(Collectors.toList())) 或 set = new HashSet(Arrays.asList(set.toArray())) 后再过滤——虽然不会报错,但效率低、内存浪费大、破坏原集合引用,仅在极特殊不可变需求下考虑,日常开发应避免。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










