我正在做:

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

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

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

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

有没有更好的解决方案?


当前回答

下面是一个在for循环中使用迭代器删除条目的代码示例。

Map<String, String> map = new HashMap<String, String>() {
  {
    put("test", "test123");
    put("test2", "test456");
  }
};

for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext(); ) {
    Map.Entry<String, String> entry = it.next();
    if(entry.getKey().equals("test")) {
        it.remove();
    }
}

其他回答

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

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

entrySet()

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

另一种更详细的方法

List<SomeObject> toRemove = new ArrayList<SomeObject>();
for (SomeObject key: map.keySet()) {
    if (something) {
        toRemove.add(key);
    }
}

for (SomeObject key: toRemove) {
    map.remove(key);
}

也许您可以遍历映射,寻找要删除的键,并将它们存储在单独的集合中。然后从映射中删除键集合。在迭代过程中修改地图通常是不受欢迎的。如果地图非常大,这个想法可能是可疑的。

ConcurrentHashMap

你可以使用java.util.concurrent.ConcurrentHashMap。

它实现了ConcurrentMap(扩展了Map接口)。

例如:

Map<Object, Content> map = new ConcurrentHashMap<Object, Content>();

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

这种方法不会影响代码。只是映射类型不同。

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();
    }
}