1

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.

2
  • I tried as many synchronized blocks as possible, but no good :( Commented Mar 12, 2012 at 10:17
  • Synchronization won't save you because this is all being caused by a single thread. Synchronization is used to serialize operations performed by multiple threads against a single non-thread-safe container such as HashMap. Commented Mar 12, 2012 at 10:43

2 Answers 2

7

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

Sign up to request clarification or add additional context in comments.

3 Comments

Exactly, the iterator is designed to allow removal of the current key/value pair while keeping the iterator in tact. The docs for entrySet specifically say that removal via remove is acceptable. Are you sure you've changed all removals to use the appropriate iterator?
In addition to the above, use Map.Entry.setValue instead of put to decrement the counter in the inner maps. The docs suggest that using put should be okay, but try this.
@DavidHarkness my bad, my bad. I over looked a HashMap.remove method. All is good and working now. thank you. Thanks for the advice too.
2

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

1 Comment

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 :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.