How to remove and add elements to TreeMap while iterating?

烈酒焚心 提交于 2019-11-28 07:20:18

问题


I want to write code like this -

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

but I got java.util.ConcurrentModificationException I tried to use Iterator also but I got the same Exception


回答1:


Explanation why it caused ConcurrentModificationException

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

for-each loop also internally create a iterator of the entrySet of map. While iterating over map you have modified the structure of the map by putting the value again to the map (map.put(x,value)) which cause this ConcurrentModificationException.

It is even well explained in documentation -

The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

How to solve this -

you must change the change the structure of this map while iterating, you can insert this values later, like keep a temporary map and add this to the main map once iteration is finished his job.

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



回答2:


Iterate over a copy and you can add/remove just fine:

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

It's not even any more lines of code, because the copy ims made in-line via the copy constructor. LinkedHashMap was chosen to preserve iteration order (if that matters).




回答3:


A sample code snippet for removing an element from the map is given below.

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

If your code involves a lot of addition and removal , you might just want to use ConcurrentHashMap.ConcurrentHashMap




回答4:


You will have to create a copy of your map using copy constructor. Now iterate on 1 and modify second map. I am assuming that you will not need to iterate newly added value as it wont make much sense.

You can achieve your task by creating a copy is because the keys will remain same in both.

EDIT:

I dont think its a good idea to iterate the newly added element to a Hashmap. If you check the api's provided by Iterator then you will find only remove method, there is no add method in it. There is a reason behind this and you can check javadoc for this. Now coming to the point, on how to iterate newly added element.

  1. Create a copy of your HashMap. So you will iterate one and modify the the other Map.
  2. As the requirement is to both add and remove elements in Map, i would like to use ListIterator for this [this is different from normal Iterator].
  3. I will get the keyset of Map1 and convert it to a list using ArrayList(Collection<? extends E> c).
  4. Now i will get ListIterator from List created in step 3, and add, remove elements in ListIterator as well as in Map2 [Remeber you need to add , remove both in ListIterator and Map2].



回答5:


Because you can't do that.

An easy solution is to use another temporary map where you put the values you want and finally switch pointers with the original one (i.e Map = newMap )



来源:https://stackoverflow.com/questions/16637026/how-to-remove-and-add-elements-to-treemap-while-iterating

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!