Java 如何在迭代时删除元素并将其添加到树映射中?
我想写这样的代码-Java 如何在迭代时删除元素并将其添加到树映射中?,java,treemap,Java,Treemap,我想写这样的代码- for (Map.Entry<Long, Integer> e : map.entrySet()){ map.remove(k); map.put(x, value); } for(Map.Entry e:Map.entrySet()){ 地图。删除(k); map.put(x,值); } 但是我得到了java.util.ConcurrentModificationException 我也尝试使用了迭代器,但我得到了相同的异常您必须使用复制构造
for (Map.Entry<Long, Integer> e : map.entrySet()){
map.remove(k);
map.put(x, value);
}
for(Map.Entry e:Map.entrySet()){
地图。删除(k);
map.put(x,值);
}
但是我得到了java.util.ConcurrentModificationException
我也尝试使用了
迭代器
,但我得到了相同的异常
您必须使用复制构造函数创建映射的副本。现在在1上迭代并修改第二个映射。
我假设您不需要迭代新增加的值,因为这没有多大意义
您可以通过创建副本来完成任务,因为这两个副本中的键保持不变
编辑:
我认为将新添加的元素迭代到Hashmap不是一个好主意。如果您检查迭代器提供的api,那么您将发现只有remove方法,而没有add方法。这背后有一个原因,您可以检查javadoc。
现在开始讨论如何迭代新添加的元素
HashMap
的副本。因此,您将迭代其中一个并修改另一个Map
Map
中添加和删除元素,因此我想使用ListIterator
来实现这一点[这与普通的迭代器不同]
键集
,并使用ArrayList(Collection将其转换为列表,因为您不能这样做
一个简单的解决方案是使用另一个临时映射,在其中放置所需的值,并最终将指针切换到原始映射(即map=newMap)解释为什么它会导致ConcurrentModificationException
对于每个循环,还可以在内部为map
的entrySet
创建一个迭代器。在对map进行迭代时,您通过将值再次放入map(map.put(x,value)
)来修改map的结构,这会导致此ConcurrentModificationException
这一点在本书中得到了很好的解释-
该类的所有“集合”视图返回的迭代器
方法“是快速失效的:如果地图在任何时候被结构修改
创建迭代器后的时间,以任何方式,除了通过
迭代器自己的remove方法,迭代器将抛出
ConcurrentModificationException。因此
修改后,迭代器会快速、干净地失败,而不是
在不确定的时间冒任意、不确定行为的风险
将来
如何解决这个问题-
您必须在迭代时更改此映射的结构,您可以稍后插入此值,例如保留一个临时映射,并在迭代完成后将其添加到主映射
Map<Long, Integer> tempMap = new HashMap<>();
for (Map.Entry<Long, Integer> e : map.entrySet()){
map.remove(k);
tempMap.put(x, value);
}
map.putAll(tempMap);
Map tempMap=newhashmap();
对于(Map.Entry e:Map.entrySet()){
地图。删除(k);
tempMap.put(x,值);
}
map.putAll(tempMap);
在副本上迭代,您可以添加/删除:
for (Map.Entry<Long, Integer> e : new LinkedHashMap<Long, Integer>(map).entrySet()){
map.remove(k);
map.put(x, value);
}
for(Map.Entry e:newlinkedhashmap(Map.entrySet()){
地图。删除(k);
map.put(x,值);
}
它甚至没有更多的代码行,因为复制ims是通过复制构造函数在线生成的。LinkedHashMap
被选择来保留迭代顺序(如果这很重要)。下面给出了从映射中删除元素的示例代码段
for(Iterator<Map.Entry<Long, Integer>> it = map.entrySet().iterator();it.next();)
{
Map.Entry<String, String> entry = it.next();
if(//some logic)
it.remove();
}
for(Iterator it=map.entrySet().Iterator();it.next();)
{
Map.Entry=it.next();
if(//某些逻辑)
it.remove();
}
如果您的代码涉及大量的添加和删除,您可能只想使用ConcurrentHashMap。否我需要迭代这些新值新添加的值将大于当前值,因此我需要迭代它们以查看我的编辑。使用新添加的步骤,您可以同时执行添加和删除。我需要迭代新添加的值Luesen做一个while循环,并一直这样做,直到你完成为止。@ZouZou我搜索了这个问题,首先发现了这个问题。Google是不够的,还需要内容:-)你能附上迭代器的代码吗。上面的代码肯定会给你一个并发修改异常。您在遍历键集的同时也在修改映射。这是造成灾难的原因。在下面添加了一个带有示例代码的答案。it.next()
不是布尔值,而且当迭代器没有更多元素时,不会为null,而是抛出java.util.NoSuchElementException
。因此,使用it.hasNext()
for(Iterator<Map.Entry<Long, Integer>> it = map.entrySet().iterator();it.next();)
{
Map.Entry<String, String> entry = it.next();
if(//some logic)
it.remove();
}