我正在做:

for (Object key : map.keySet())
    if (something)
        map.remove(key);

它抛出了一个ConcurrentModificationException,所以我把它改为:

for (Object key : new ArrayList<Object>(map.keySet()))
    if (something)
        map.remove(key);

这个过程以及修改映射的任何其他过程都在同步块中。

有没有更好的解决方案?


当前回答

我同意Paul Tomblin的观点。我通常使用键集的迭代器,然后以该键的值为条件:

Iterator<Integer> it = map.keySet().iterator();
while(it.hasNext()) {
    Integer key = it.next();
    Object val = map.get(key);
    if (val.shouldBeRemoved()) {
        it.remove();
    }
}

其他回答

在遍历映射时,必须使用Iterator来安全地删除元素。

使用真正的迭代器。

Iterator<Object> it = map.keySet().iterator();

while (it.hasNext())
{
  it.next();
  if (something)
    it.remove();
 }

实际上,您可能需要遍历entrySet()而不是keySet()才能使其工作。

从Java 8开始,你可以这样做:

map.entrySet().removeIf(e -> <boolean expression>);

entrySet()

集合是由映射支持的,所以对映射的更改会反映在集合中,反之亦然

有没有更好的解决方案?

当然,在单个语句中有更好的方法,但这取决于基于删除哪些元素的条件。

例如:删除所有值为test的元素,然后使用下面的代码:

map.values().removeAll(Collections.singleton("test"));

更新 这可以在一行中使用Java 8中的Lambda表达式完成。

map.entrySet().removeIf(e-> <boolean expression> );

我知道这个问题太老了,但更新更好的做事方式并没有什么坏处:)

Set s=map.entrySet();
Iterator iter = s.iterator();

while (iter.hasNext()) {
    Map.Entry entry =(Map.Entry)iter.next();

    if("value you need to remove".equals(entry.getKey())) {
         map.remove();
    }
}