0

I am having trouble with a Concurrent modification exception. I have changed my code to use iterators however I am still getting these issues when I remove an object. My error occurs on the line

theEnemy = (Enemy) EnemyItr.next();

I'm not sure how I would get around this as it is a very important part of the code.

for (Iterator EnemyItr = activeEnemies.iterator(); EnemyItr.hasNext(); ){

    theEnemy = (Enemy) EnemyItr.next(); 
    try {

        try {

            if (theEnemy.x < 0 && theEnemy.y >= 5) {
                activeEnemies.remove(theEnemy);
            }
        } catch (Exception e) {
            System.err.println("Cannot Remove Enemy");
        }

        Enemy.pathFind(Enemy.getXBlockOfEnemy(theEnemy.x), Enemy.getXBlockOfEnemy(theEnemy.y), theEnemy.x, theEnemy.y);

        if (Enemy.right) {
            theEnemy.x += Enemy.speed;
            //System.out.println("right");
            //System.out.println(theEnemy.x + " " + theEnemy.y);
        } else if (Enemy.down) {
            theEnemy.y += Enemy.speed;
            //System.out.println("down");
            //System.out.println(theEnemy.x + " " + theEnemy.y);;
        } else if (Enemy.up) {
            theEnemy.y -= Enemy.speed;
            //System.out.println("up");
            //System.out.println(theEnemy.x + " " + theEnemy.y);
        } else if (Enemy.left) {
            theEnemy.x -= Enemy.speed;
            //System.out.println("left");
            //System.out.println(theEnemy.x + " " + theEnemy.y);
        } else {
            System.out.println("Enemy Lost.");
            //System.out.println(theEnemy.x + " " + theEnemy.y);
        }

        g.drawImage(enemy, theEnemy.x, theEnemy.y, this);
        //System.out.println(Enemy.getXBlockOfEnemy(theEnemy.x));

        //drawing health bar
        if (Input.displayUI) {
            g.setColor(Color.LIGHT_GRAY);
            g.fillRect(theEnemy.x, theEnemy.y - 10, 70, 10);
            g.setColor(Color.RED);
            g.fillRect(theEnemy.x + 2, theEnemy.y - 10 + 1, 68, 8);
            g.setColor(Color.GREEN);
            g.fillRect(theEnemy.x + 2, theEnemy.y - 10 + 1, (int) (.68 * theEnemy.enemylife), 8);
        }

    } catch (ConcurrentModificationException e) {
        theEnemy = null;
    }

}
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Nick Haughton
  • 99
  • 1
  • 11
  • The exception is pretty self-explanatory: you can't modify a collection through which you are iterating. You do that when you remove the enemy from the list. (And don't just catch exceptions like that; they are telling you something is wrong with your code that you need to fix.) – dlev May 16 '13 at 18:55
  • @dlev Yes, I understand that but I don't see how to fix it, I cannot just remove the code that sets the next object. – Nick Haughton May 16 '13 at 18:56
  • You need to use a different mechanism to iterate your collection in this case. Or, create a copy of the collection, iterate that, and remove the object from the original list. – dlev May 16 '13 at 18:57

3 Answers3

3

The only chance to remove an element from a collection while iterating over it is to use the remove() method of the iterator itself. But since this is an optional method you may have to use the suggestions from the other answers here if your iterator doesn't support the remove method.

In short: use the remove method of the iterator instead of the remove method of the collection itself.

mschenk74
  • 3,561
  • 1
  • 21
  • 34
1

The issue is that the collection that you are iterating does not support modification while being iterated.

ConcurrentModificationException

It is a common need to filter out 'bad' entries from a collection. Typically, I would do it in this way:

public void filter(Collection<MyObject> myObjectsToFilter) {
    final Collection<MyObject> toRemove = new HashSet<MyObject>();
    for(MyObject myObject : myObjectsToFilter) {
        if(myObject.specificCondition()) {
            toRemove.add(myObject);
        }
    }
    myObjectsToFilter.removeAll(toRemove);
}

This example keeps a separate collection of objects to remove. It is built up while the iteration is happening, and after iteration is complete, it removes all of the entries.

nicholas.hauschild
  • 42,483
  • 9
  • 127
  • 120
1

A typical solution is to create a List, say, removeList, of all the items to be removed. Instead of immediately removing the Enemy during your loop, add it to removeList. At the end of your loop, call activeEnemies.removeAll(removeList);

An advantage of this way is that you don't need to bother with iterators, you can just loop over the original collection.

If you do choose to use an iterator, use it's remove method, as described by @mschenk74

user949300
  • 15,364
  • 7
  • 35
  • 66