2013-05-16 3 views
0

Je rencontre des problèmes avec une exception de modification simultanée. J'ai changé mon code pour utiliser les itérateurs, mais je rencontre toujours ces problèmes lorsque je supprime un objet. Mon erreur se produit sur la ligneException de modification simultanée avec des objets

theEnemy = (Enemy) EnemyItr.next();

Je ne sais pas comment je contourner ce qu'il est une partie très importante du 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; 
    } 

} 
+0

L'exception est assez explicite: vous ne pouvez pas modifier une collection à travers laquelle vous itérez. Vous faites cela lorsque vous supprimez l'ennemi de la liste. (Et ne pas attraper des exceptions comme ça, ils vous disent que quelque chose ne va pas avec votre code que vous devez corriger.) – dlev

+0

@dlev Oui, je comprends cela, mais je ne vois pas comment le réparer, je ne peux pas juste supprimer le code qui définit l'objet suivant. –

+0

Vous devez utiliser un mécanisme différent pour itérer votre collection dans ce cas. Vous pouvez également créer une copie de la collection, l'itérer et supprimer l'objet de la liste d'origine. – dlev

Répondre

3

La seule chance de supprimer un élément d'une collection en l'itérant est d'utiliser la méthode remove() de l'itérateur lui-même. Mais comme il s'agit d'une méthode facultative, vous devrez peut-être utiliser les suggestions des autres réponses ici si votre itérateur ne supporte pas la méthode remove. En bref: utilisez la méthode remove de l'itérateur au lieu de la méthode remove de la collection elle-même.

+0

+1. Voir ma réponse pour une alternative sans utiliser d'itérateurs. – user949300

+0

Wow, c'est génial! Merci beaucoup @ mschenk74 –

1

Le problème est que la collection que vous itérez ne prend pas en charge la modification lors de l'itération.

ConcurrentModificationException

Il est un besoin commun de filtrer les entrées « mauvais » d'une collection. En général, je le ferais de cette façon:

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); 
} 

Cet exemple conserve une collection séparée d'objets à supprimer. Il est construit pendant l'itération, et une fois l'itération terminée, il supprime toutes les entrées.

1

Une solution type consiste à créer une liste, par exemple removeList, de tous les éléments à supprimer. Au lieu de supprimer immédiatement l'ennemi pendant votre boucle, ajoutez-le au removeList. A la fin de votre boucle, appelez activeEnemies.removeAll(removeList);

Un avantage de cette façon est que vous n'avez pas besoin de vous embêter avec les itérateurs, vous pouvez simplement faire une boucle sur la collection d'origine.

Si vous choisissez d'utiliser un itérateur, utiliser Supprimons méthode, tel que décrit par @ mschenk74

Questions connexes