2

I am trying to avoid the Concurrent Modification Exception. I loop over an entities HashMap to tick() each entity. Player entity moves around screen with WASD input, and to test addNewEntity() method I call GameState.addNewEntity(new Explosion(true, this.x, this.y)); when player moves right. Several explosions appear over player and then I get an error. Player class extends Creature which extends Entity. Explosion extends Entity class.

This code is from my GameState class:

private static HashMap<Integer, Entity> entities = new HashMap<Integer, Entity>();
private static HashMap<Integer, Entity> newEntities = new HashMap<Integer, Entity>();

player = new Player(game, true, 100, 100);
entities.put(0, player);

My tick() method:

public void tick() {
    // add new elements from newEntities to entities, deleting from newEntities
    for (Entry<Integer, Entity> entry : newEntities.entrySet()) { 
        entities.put(entities.size(), entry.getValue());
        newEntities.remove(entry.getValue());
    }

    System.out.println(entities.size());

    // tick the updated entities HashMap
    for (Entry<Integer, Entity> entry : entities.entrySet()) { 
        entry.getValue().tick();

        // remove dead entities
        if (!entry.getValue().isAlive) {
             entities.remove(entry.getKey());
        }
    }
}

my addNewEntity method:

public static void addNewEntity(Entity e) {
    // add a new element to newEntities. 
    newEntities.put(newEntities.size(), e);
}

my render method:

public void render(Graphics g) {
    for (Entry<Integer, Entity> entry : entities.entrySet()) { 
        entry.getValue().render(g);
    }
}

I tried to avoid the Concurrent Modification Exception by adding to the newEntities HashMap instead of adding to the entities HashMap. In my tick method, I loop over the newEntities HashMap and add each item that exsists there to entities, deleting each one in turn. Only after that do I loop over the entities HashMap.

How is it possible that I am Modifying the Map while Iterating over it?

1 Answer 1

1

Removing an entry from a Map directly while iterating over it with the enhanced for loop is not allowed. Instead, use an explicit iterator to iterate, and the iterator's remove() method.

Iterator<Map.Entry<Integer, Entity>> iter = newEntities.entrySet().iterator();
while (iter.hasNext()) { 
    Map.Entry<Integer, Entity> entry = iter.next();
    entities.put(entities.size(), entry.getValue());
    iter.remove();
}

Do the same for the second loop.

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

1 Comment

Thanks Eran. Worked like a charm.

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.