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:
What could be causing this? This is the only code that is iterating the HashMap:
And then there are a couple methods earlier that populate the HashMap:
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)
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);
}
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);
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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).
ASKER
Thanks :). How could I change the following code to work with that synchronized feature?
And also what import statements do I need to use for it to work?
private HashMap<String, Entity> entities = new HashMap<String, Entity>();
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.synchronizedMa p(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
Map m = Collections.synchronizedMa
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.
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.
T think this has relevant information over how you iterate the HashMap:
http://stackoverflow.com/questions/1066589/java-iterate-through-hashmap