迭代时如何删除和添加元素到TreeMap?

我想写这样的代码 –

for (Map.Entry e : map.entrySet()){ map.remove(k); map.put(x, value); } 

但是我得到了java.util.ConcurrentModificationException我也试过使用Iterator但是我得到了相同的Exception

解释它导致ConcurrentModificationException

 map.remove(k); map.put(x, value); 

for-each循环还在内部创建mapentrySet的迭代器。 在迭代map时,您已经通过将值再次放到映射( map.put(x,value) )来修改映射的结构,这会导致此ConcurrentModificationException

它甚至在文档中得到了很好的解释 –

所有这个类的“集合视图方法”返回的迭代器都是快速失败的:如果在创建迭代器之后的任何时候对映射进行结构修改,除了通过迭代器自己的remove方法之外,迭代器将抛出ConcurrentModificationException。 。 因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒任意,非确定性行为的风险。

如何解决这个问题

你必须在迭代时改变这个地图的结构,你可以在以后插入这个值,比如保留一个临时地图,并在迭代完成后添加这个值。

 Map tempMap = new HashMap<>(); for (Map.Entry e : map.entrySet()){ map.remove(k); tempMap.put(x, value); } map.putApp(tempMap); 

迭代一个副本,你可以添加/删除就好了:

 for (Map.Entry e : new LinkedHashMap(map).entrySet()){ map.remove(k); map.put(x, value); } 

它甚至不再是代码行,因为复制ims是通过复制构造函数在线进行的。 选择LinkedHashMap来保留迭代顺序(如果这很重要)。

您必须使用复制构造函数创建地图的副本。 现在迭代1并修改第二个地图。 我假设您不需要迭代新增加的值,因为它没有多大意义。

您可以通过创建副本来完成任务,因为密钥在两者中都保持相同。

编辑:

我不认为将新添加的元素迭代到Hashmap是一个好主意。 如果你检查Iterator提供的api,你会发现只有remove方法,其中没有add方法。 这有一个原因,你可以检查javadoc。 现在谈谈如何迭代新添加的元素。

  1. 创建HashMap的副本。 因此,您将迭代一个并修改另一个Map
  2. 由于要求在Map添加和删​​除元素,我想使用ListIterator [这与普通的Iterator不同]。
  3. 我将获取Map1的keyset并使用ArrayList(Collection c)将其转换为列表ArrayList(Collection c)
  4. 现在我将从步骤3中创建的List中获取ListIterator,并添加,删除ListIterator和Map2中的元素[记住你需要添加,删除ListIterator和Map2中的元素]。

下面给出了用于从地图中删除元素的示例代码段。

 for(Iterator> it = map.entrySet().iterator();it.next();) { Map.Entry entry = it.next(); if(//some logic) it.remove(); } 

如果您的代码涉及大量添加和删除,您可能只想使用ConcurrentHashMap。 的ConcurrentHashMap

因为你做不到。

一个简单的解决方案是使用另一个临时映射,您可以在其中放置所需的值,最后使用原始映射切换指针(即Map = newMap)