sasidhar
sasidhar

Reputation: 7752

How to iterate over a HashMap while avoiding ConcurrentModificationException

I have a HashMap, its of the type HashMap<String,HashMap<String,int>> now i need to iterate over this HashMap and delete the inner HashMaps that have a value of 0 for any key.

If such a removal makes the inner HashMap empty then the inner HashMap's corresponding key is removed from the outer HashMap. I tried iterating over it and then removing elements that match the requirements, but that throws me a ConcurrentModificationException.

I tried the following code:

synchronized(MyConstants.cliListUpdateList)
{
    synchronized(MyConstants.cliList)
    {
        outerEntries = MyConstants.cliListUpdateList.entrySet();
        outerIterator = outerEntries.iterator();

        while(outerIterator.hasNext())
        {
            outerEnt = (Entry) outerIterator.next();
            innerHashMap = (HashMap) outerEnt.getValue();
            synchronized(innerHashMap)
            {//synchronize innerhashmap
            innerEntries = innerHashMap.entrySet();
            innerIterator = innerEntries.iterator();
            synchronized(innerIterator)
            {
            while(innerIterator.hasNext())
            {
                innerEnt = (Entry) innerIterator.next();
                int k = Integer.parseInt((String)innerEnt.getValue());
                if(k==0)
                {
                    innerHashMap.remove(innerEnt.getKey());
                    if(innerHashMap.isEmpty())
                    {
                        MyConstants.cliListUpdateList.remove(outerEnt.getKey());
                    }

                    ArrayList ports = (ArrayList) MyConstants.cliList.get(outerEnt.getKey());
                    ports.remove((String)innerEnt.getKey());
                    if(ports.isEmpty())
                    {
                        MyConstants.cliList.remove(outerEnt.getKey());
                    }
                }
                else
                {
                    k--;
                    innerHashMap.put(innerEnt.getKey(), k+"");
                    MyConstants.cliListUpdateList.put(outerEnt.getKey(), innerHashMap);
                }

            }
            }
        }//synchronize innerhashmap
        }


        System.out.println(MyConstants.cliListUpdateList + " <---> "+ MyConstants.cliList);

    }
}

I am getting the exception at this line: innerEnt = (Entry) innerIterator.next();. I tried the remove method provided by the Iterator class. But that is also no good.

EDIT

from the Java docs I know this much if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this(ConcurrentModificationException) exception but I need exactly the same functionality.

Upvotes: 1

Views: 1441

Answers (2)

OldCurmudgeon
OldCurmudgeon

Reputation: 65811

May not solve your problem completely but instead of innerHashMap.remove(innerEnt.getKey()); you need to use the iterator's remove method innerIterator.remove();

Upvotes: 7

Michael Laffargue
Michael Laffargue

Reputation: 10304

Did you try using Synchronized Hashmap ? Collections.synchronizedMap(new HashMap()) or take a look at ConcurrentHashMap

Upvotes: 2

Related Questions