迭代并从地图中删除

我在做:

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

抛出一个ConcurrentModificationException,所以我改变它:

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

这个和修改地图的任何其他过程都在同步块中。

有更好的解决scheme吗?

如果没有人提出更好的解决scheme,首先要说没有得到滴答声;)

这是一个代码示例,使用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 1.8开始,您可以使用lambdaexpression式和stream来实现这一点:

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

使用一个真正的迭代器。

 Iterator<Object> it = map.keySet().iterator(); while (it.hasNext()) { it.next(); if (something) it.remove(); } 

实际上,您可能需要迭代entrySet()而不是keySet()来使其工作。

有更好的解决scheme吗?

那么,在一个声明中肯定有一个更好的方法,但这取决于基于哪些元素被删除的条件。

例如:删除所有这些元素的value testing ,然后使用下面:

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

更新它可以在Java 8中使用Lambdaexpression式在一行中完成。

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

我知道这个问题太老了, 但更新更好的方式来做事情没有任何伤害:)

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

这种方法不会影响你的代码。 只有maptypes不同。

Java 8支持迭代的更多声明式方法,因为我们指定了我们想要的结果,而不是如何计算它。 新方法的好处是它可以更易读,更不容易出错。

 public static void mapRemove() { Map<Integer, String> map = new HashMap<Integer, String>() { { put(1, "one"); put(2, "two"); put(3, "three"); } }; map.forEach( (key, value) -> { System.out.println( "Key: " + key + "\t" + " Value: " + value ); }); map.keySet().removeIf(e->(e>2)); System.out.println("After removing element"); map.forEach( (key, value) -> { System.out.println( "Key: " + key + "\t" + " Value: " + value ); }); } 

结果如下:

 Key: 1 Value: one Key: 2 Value: two Key: 3 Value: three After removing element Key: 1 Value: one Key: 2 Value: two 

遍历地图时,必须使用Iterator来安全地移除元素。

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

也许你可以遍历地图寻找键来删除和存储在一个单独的集合。 然后从地图上删除键的集合。 迭代时修改地图通常是不被接受的。 如果地图非常大,这个想法可能会受到怀疑。

另一种更详细的方式

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

这应该也是一样

 running is ConcurrentMap<Integer, String> Set<Entry<Integer, String>> set = running.entrySet(); for (Entry<Integer, String> entry : set ) { if (entry.getKey()>600000) { set.remove(entry); } } 
  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(); } }