Link to home
Start Free TrialLog in
Avatar of Eindoofus
Eindoofus

asked on

Why is the HashMap iterator intermittently failing?

There are times when I start my program and it runs fine and then other times when it spits out this error:

Exception in thread "Thread-3" java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
	at java.util.HashMap$EntryIterator.next(HashMap.java:847)
	at java.util.HashMap$EntryIterator.next(HashMap.java:845)
	at domain.EntityManager$UpdateLoop.updateContent(EntityManager.java:130)
	at domain.EntityManager$UpdateLoop.run(EntityManager.java:111)
	at java.lang.Thread.run(Thread.java:722)

Open in new window


What could be causing this? This is the only code that is iterating the HashMap:

            for (Map.Entry<String, Entity> entry : entities.entrySet()) {
                String key = entry.getKey();
                Entity item = entry.getValue();
                if (item.isDestroyed()){
                    entities.remove(key);
                    ViewManager.getInstance().removeItem(key);
                    //INSTRUCT THE ENTITY TO PERFORM IT'S DESTROYED BEHAVIOR item.Destroyed()                    
                } else {
                    item.update(1);
                    ConsoleItem ci = new ConsoleItemImpl(item.getIdentifier(), item.getLocation(), ColorStringConverter.getInstance().StringToColor(item.getSide()), item.getAngle(), item.getShape(), item.toString(), item.isDestroyed(), item.isDamaged());
                    ViewManager.getInstance().updateItem(ci);                    
                }
                item.update(1);
            }

Open in new window


And then there are a couple methods earlier that populate the HashMap:

    public void initialize(String side, int ships, int charges, double speed) throws InvalidDataException {
        for (int i=0; i < ships; i++) {                                   
            cs = new CargoShip(side, charges, speed);       
            entities.put(cs.getIdentifier(), cs);            
        }
    }
    
    public void initializeClouds(int clouds, int duration, double size) throws InvalidDataException {
        for (int i=0; i < clouds; i++) {                                   
            dc = new DebrisCloud(duration, size);       
            entities.put(dc.getIdentifier(), dc);            
        }        
    }

Open in new window




ASKER CERTIFIED SOLUTION
Avatar of for_yan
for_yan
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial


T think this has relevant information over how you iterate the HashMap:
http://stackoverflow.com/questions/1066589/java-iterate-through-hashmap


In particular read this remark in the above link:
One caveat: if you want to remove items mid-iteration, you'll need to do so via an Iterator (see karim79's answer). However, changing item values is OK (see Map.Entry).
Avatar of Eindoofus
Eindoofus

ASKER

Thanks :). How could I change the following code to work with that synchronized feature?

private HashMap<String, Entity> entities = new HashMap<String, Entity>();

Open in new window


And also what import statements do I need to use for it to work?
I think their suggestion is to create the hashMap in this way:

 Map m = Collections.synchronizedMap(new HashMap(...));

In this stackoverflow link they suggest to change the way you iterate and use
explicit iterator, as you are removing the entries, just as they mentioned


Maybe another way is to use old-style Hashtable ?

I would also think about removing entries outside of iteration loop - I'd mark them, say make a list of them  and remove directly
outside of iteration process.
Well, no one suggests it, but it kind of seems safer to me - not very well understand how it happens iteration with simulatneous removal
of entries over which iteration is going.

But I would rather be trying all these options starting with the simplest - say change the way of iteration to explicit iterator
as those folks in stackoverflow suggest.