2013-05-16 2 views
0

У меня возникла проблема с исключением параллельной модификации. Я изменил свой код, чтобы использовать итераторы, но я все еще получаю эти проблемы при удалении объекта. Моя ошибка возникает на линииИсключение с одновременным изменением с объектами

theEnemy = (Enemy) EnemyItr.next();

Я не знаю, как я бы обойти эту проблему, так как это очень важная часть кода.

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

Исключением является довольно очевидно: вы не можете изменять коллекцию, через которую вы итерация. Вы делаете это, когда вы удаляете врага из списка. (И не просто поймайте такие исключения, они сообщают вам, что что-то не так с вашим кодом, который вам нужно исправить.) – dlev

+0

@dlev Да, я это понимаю, но я не понимаю, как это исправить, я не могу просто удалите код, который устанавливает следующий объект. –

+0

В этом случае вам необходимо использовать другой механизм для повторной обработки вашей коллекции. Или создайте копию коллекции, повторите ее и удалите объект из исходного списка. – dlev

ответ

3

Единственный шанс удалить элемент из коллекции при итерации по нему - использовать метод remove() самого итератора. Но поскольку это необязательный метод, вам, возможно, придется использовать предложения из других ответов здесь, если ваш итератор не поддерживает метод удаления.

Вкратце: используйте метод удаления итератора вместо метода удаления самой коллекции.

+0

+1. См. Мой ответ для альтернативного пути без использования итераторов. – user949300

+0

Ничего себе, это блестяще! Большое спасибо @ mschenk74 –

1

Проблема в том, что коллекция, которую вы итерируете, не поддерживает модификацию при повторении.

ConcurrentModificationException

Это общая потребность, чтобы отфильтровать «плохие» записи из коллекции. Как правило, я бы сделал это таким образом:

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

В этом примере хранится отдельная коллекция объектов для удаления. Он создается, пока итерация происходит, и после завершения итерации она удаляет все записи.

1

Типичным решением является создание списка, скажем, removeList, всех предметов, подлежащих удалению. Вместо того, чтобы немедленно удалить Врага во время цикла, добавьте его в removeList. В конце вашего цикла звоните activeEnemies.removeAll(removeList);

Преимущество этого способа в том, что вам не нужно беспокоиться об итераторах, вы можете просто перебрать исходную коллекцию.

Если вы решили использовать итератор, использовать его удалить метод, как описано @ mschenk74

Смежные вопросы