Java中用for-each遍历HashMap触发ConcurrentModificationException异常
HashMap遍历删除元素抛出ConcurrentModificationException的解决方法
直接在for-each循环中调用wordbank.remove(s)会触发ConcurrentModificationException,原因是HashMap的keySet迭代器是**快速失败(fail-fast)**的:当迭代器创建后,若集合结构被修改(如添加、删除元素),迭代器会检测到内部的modCount和expectedModCount不匹配,立刻抛出异常。for-each循环本质依赖迭代器实现,直接调用集合的remove方法不属于迭代器允许的修改操作。
下面是几种可行的解决方式:
方法1:使用迭代器的remove方法
这是标准的安全遍历删除方式,迭代器的remove()方法会同步更新内部计数,避免异常:
void wordsContainingLetter(char c) { Iterator<String> iterator = wordbank.keySet().iterator(); while (iterator.hasNext()) { String s = iterator.next(); boolean contains = false; for (char ch : s.toCharArray()) { if (ch == c) { contains = true; break; } } if (!contains) { iterator.remove(); // 使用迭代器自身的remove方法 } } }
方法2:使用Java 8+的removeIf方法
Java 8及以上版本可以用更简洁的removeIf方法,内部会安全处理迭代与删除逻辑:
void wordsContainingLetter(char c) { wordbank.keySet().removeIf(s -> { for (char ch : s.toCharArray()) { if (ch == c) { return false; // 包含目标字符,不删除 } } return true; // 不包含目标字符,执行删除 }); }
如果想进一步简化字符检查逻辑,直接用String.contains():
void wordsContainingLetter(char c) { wordbank.keySet().removeIf(s -> !s.contains(String.valueOf(c))); }
方法3:先收集待删除Key,再批量删除
先遍历keySet,将需要删除的key存入临时集合,之后统一批量删除:
void wordsContainingLetter(char c) { List<String> toRemove = new ArrayList<>(); for (String s : wordbank.keySet()) { boolean contains = false; for (char ch : s.toCharArray()) { if (ch == c) { contains = true; break; } } if (!contains) { toRemove.add(s); } } wordbank.keySet().removeAll(toRemove); }
内容的提问来源于stack exchange,提问作者alex miranda
相关产品推荐
相关产品推荐

