如何在遍历HashMap时删除一个键?

181

我有一个名为testMapHashMap,其中包含String, String

HashMap<String, String> testMap = new HashMap<String, String>();

在迭代map时,如果value与指定的字符串匹配,我需要从map中删除这个键。

例如:

for(Map.Entry<String, String> entry : testMap.entrySet()) {
  if(entry.getValue().equalsIgnoreCase("Sample")) {
    testMap.remove(entry.getKey());
  }
}

testMap 包含 "Sample",但我无法从 HashMap 中删除该键。而是会出现错误:

"Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
    at java.util.HashMap$EntryIterator.next(Unknown Source)
    at java.util.HashMap$EntryIterator.next(Unknown Source)"

1
请始终复制/粘贴代码片段,而不是输入“类似于”所使用的代码。原始代码显示无法引发运行时异常,因为它无法编译。 - Andrew Thompson
1
另一个选项,虽然有些笨拙,是在迭代时创建一个要删除的对象列表。然后,在初始循环之后,您可以创建另一个循环,遍历该列表并将它们从哈希映射中删除。 - eipark
2个回答

379

尝试:

Iterator<Map.Entry<String,String>> iter = testMap.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry<String,String> entry = iter.next();
    if("Sample".equalsIgnoreCase(entry.getValue())){
        iter.remove();
    }
}

从Java 1.8开始,你可以只用一行代码完成上述操作:

testMap.entrySet().removeIf(entry -> "Sample".equalsIgnoreCase(entry.getValue()));

7
如果你想要删除的项并不是迭代器所指向的那一项,该怎么办? - Dave
9
可以使用类似于 Map.remove (Object key) 的方法,但不应在迭代期间执行。如果在迭代过程中使用除 Iterator.remove() 之外的任何删除方法,则迭代结果未定义。要么等到迭代器"处于"您想要删除的条目上并使用Iterator.remove(),要么在迭代循环之外(之前/之后)执行此操作。如果是后者,请确保在对映射进行任何迭代之前从条目集获取新的迭代器,因为任何先前的迭代器都会产生未定义的结果。 - user711807
2
或者您可以使用具有类似语义的 for 循环,请参见 https://dev59.com/z3I-5IYBdhLWcg3wYnOQ#1884916。 - rogerdpack
1
很多年前,在Java 8之前,我遇到了这个问题,我使用了ConcurrentHashMap而不是HashMap。 - Mehdi

16

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接