3

I am getting the below error while using map and performing some remove.How to avoid this ?

Caused by: java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
    at java.util.HashMap$EntryIterator.next(HashMap.java:834)
    at java.util.HashMap$EntryIterator.next(HashMap.java:832)


   Map<FormField, Object> ItemMap = domainItem.getValues();         
   for (Map.Entry<FormField, Object> ValMap : ItemMap.entrySet()) {         
       List<Field> groupIdList = Mapper.getGroupId(groupFieldId);           
       for (Field field : groupIdList) {
           ItemMap.put(new FormField(field), domainItem.getDomainItemLinkId());
       }
       ItemMap.remove(ValMap.getKey());
   }
basiljames
  • 4,777
  • 4
  • 24
  • 41
pars
  • 153
  • 2
  • 4
  • 11

4 Answers4

11

Update:

Use Iterator and ConcurrentHashMap to avoid this scenario

Following won't throw exception

    Map<Integer, String> map = new ConcurrentHashMap<Integer, String>();
    map.put(1, "a");
    map.put(2, "b");
    map.put(3, "c");
    map.put(4, "d");
    for (Iterator<Integer> keys = map.keySet().iterator(); keys.hasNext();) {
        Integer key = keys.next();
        String val = map.get(key);
        map.remove(key);
    }

or use another map while iterating and at the end copy it to source

for example:

    Map<Integer, String> dummy = new HashMap<Integer, String>();
    map.put(1, "a");
    map.put(2, "b");
    map.put(3, "c");
    map.put(4, "d");
    dummy.putAll(map);
    for (Iterator<Integer> keys = dummy.keySet().iterator(); keys.hasNext();) {
        Integer key = keys.next();
        String val = map.get(key);
        map.remove(key);
    }
    System.out.println(map);
jmj
  • 237,923
  • 42
  • 401
  • 438
0

A Map is sorted by the keys in the key-value pairs. When you add or remove elements from the Map while you are iterating through them, the program essentially loses track of "where" in the Map it is.

To get around this, try making a separate, temporary transfer Map. There is also a class called Iterator which might suit your needs.

asteri
  • 11,402
  • 13
  • 60
  • 84
0

One way to avoid this issue is to iterate over a copy.

for (Map.Entry<FormField, Object> ValMap : 
     new HashMap<FormField, Object>(ItemMap).entrySet()) {
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • if i create a copy then i can use for (Field field : groupIdList) { ItemMap.put(new FormField(field), domainItem.getDomainItemLinkId()); } ItemMap.remove(ValMap.getKey()); – pars Sep 11 '12 at 10:57
  • Its not possible to say from the code you have given as your interaction is very complicated. I would move this code into the class of `domainItem` so you can see all the dependencies. – Peter Lawrey Sep 11 '12 at 11:01
  • Map ItemMap = domainItem.getValues(); for (Map.Entry ValMap : new HashMap(ItemMap).entrySet()) { List groupIdList = Mapper.getGroupId(groupFieldId); for (Field field : groupIdList) { ItemMap.put(new FormField(field), domainItem.getDomainItemLinkId()); } ItemMap.remove(ValMap.getKey()); } – pars Sep 11 '12 at 11:03
  • You need to include the code for all the methods called in case there are side effects, which is why suggest you put all the code in one place. The reason I am concerned is that half the loop doesn't appear to need to be there so there must be something going on which I cannot see. ;) – Peter Lawrey Sep 11 '12 at 11:04
  • can u please explain with some other solution,iterator or so.Seems not to be working out in my case – pars Sep 11 '12 at 11:07
  • Its impossible to say what you should do without know what you are trying to achieve. It doesn't make any sense as it is. – Peter Lawrey Sep 11 '12 at 11:09
  • i want to loop over map and add some data to it,removing the previous one.So i m doing as mentioned above – pars Sep 11 '12 at 11:11
0

can be done without a copy of the map, execute this example and take a look at the code:

public static void main(String[] args)
  {

    System.out.println("creating map ...");

    Map<String, String> dummyMap = new HashMap<>();
    while (dummyMap.size() < 10)
    { dummyMap.put(String.valueOf(new Random().nextInt()), String.valueOf(new Random().nextInt())); }


    System.out.println("start, map size: " + dummyMap.size() + ", keys=" + dummyMap.keySet());


    System.out.print("going to remove: ");
    for (Iterator<String> keys = dummyMap.keySet().iterator(); keys.hasNext(); )
    {
      final String key = keys.next();

      // delete map entries per random
      if(new Random().nextInt(3)>1)
      {
        System.out.print(key+" ");
        keys.remove();
      }
    }
    System.out.print("\n");

    System.out.println("done, map size: " + dummyMap.size() + ", keys=" + dummyMap.keySet());
  }

and take a look at this similar question.

HTH,

Community
  • 1
  • 1
Chris
  • 15,429
  • 19
  • 72
  • 74