2014-10-17 3 views
2

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

public void forward() 
{ 
    for (Sprite s : sprites) 
    { 
     s.move(); 
     for (Iterator<Sprite> iter = sprites.iterator(); iter.hasNext();) 
     { 
      s = iter.next(); 
      if (s instanceof Attacker) 
      { 
       for (Sprite s2 : sprites) 
       { 
        if(s.overlaps(s2)) 
         s2.hit(); 
       } 
      } 
      if (s.shouldRemove()) 
       iter.remove(); 
     } 
    } 
} 

это работает примерно первые 15 до 20 раз и то я получаю ошибку каждой пару кликов

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException 
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) 
at java.util.ArrayList$Itr.next(ArrayList.java:851) 
at Model.forward(Model.java:46) 
at Controller.mousePressed(Controller.java:29) 
at java.awt.Component.processMouseEvent(Component.java:6522) 
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321) 
at java.awt.Component.processEvent(Component.java:6290) 
at java.awt.Container.processEvent(Container.java:2234) 
at java.awt.Component.dispatchEventImpl(Component.java:4881) 
at java.awt.Container.dispatchEventImpl(Container.java:2292) 
at java.awt.Component.dispatchEvent(Component.java:4703) 
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898) 
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4530) 
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462) 
at java.awt.Container.dispatchEventImpl(Container.java:2278) 
at java.awt.Window.dispatchEventImpl(Window.java:2739) 
at java.awt.Component.dispatchEvent(Component.java:4703) 
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746) 
at java.awt.EventQueue.access$400(EventQueue.java:97) 
at java.awt.EventQueue$3.run(EventQueue.java:697) 
at java.awt.EventQueue$3.run(EventQueue.java:691) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86) 
at java.awt.EventQueue$4.run(EventQueue.java:719) 
at java.awt.EventQueue$4.run(EventQueue.java:717) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
at java.awt.EventQueue.dispatchEvent(EventQueue.java:716) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 

Я не совсем уверен, которое выбрасывает ошибку

+1

, какая линия метания ошибки? – dkatzel

+0

какая строка в вашем примере - строка 46 в вашем файле («Model.forward (Model.java:_46_)»)? – jtahlborn

+0

'for (Sprite s: спрайты)' – cwendel

ответ

2

Вы получаете ConcurrentModificationException, потому что вы удаляете элемент из коллекции во время итерации по этой коллекции, кроме как через итератор. В этом случае у вас нет явного итератора для внешней итерации, поэтому нет способа безопасно модифицировать коллекцию sprites внутри цикла.

Лучшее, что вы можете сделать, это, вероятно, собрать элементы для удаления во временную коллекцию, а затем удалить их все после цикла, что-то вроде этого:

Set<Sprite> toRemove = new HashSet<Sprite>(); 

for (Sprite s1 : sprites) { 
    if (toRemove.contains(s1)) { 
     continue; 
    } 
    s1.move(); 
    for (Sprite s : sprites) { 
     if (toRemove.contains(s)) { 
      continue; 
     } 
     if (s instanceof Attacker) { 
      for (Sprite s2 : sprites) { 
       if (toRemove.contains(s2)) { 
        continue; 
       } 
       if(s.overlaps(s2)) { 
        s2.hit(); 
       } 
      } 
     } 
     if (s.shouldRemove()) { 
      toRemove.add(s); 
     } 
    } 
} 

sprites.removeAll(toRemove); 
+0

Нет, * внешний * цикл (в исходном коде) является 'for (Sprite s: sprites) {...}' , 'iter' является итератором для * среднего * цикла. –

+0

святая корова, как я пропустил это! я прочитал этот код 10 раз и пропустил этот внешний цикл. – jtahlborn

+1

Отмена удаления может изменить поведение, если какой-либо из методов, вызванных на экземплярах 'Sprite' (' move() ',' overlaps (Sprite) ',' hit() 'и' shouldRemove() '), использует коллекцию' sprites' , Если это так, то все это, вероятно, нужно пересмотреть. –

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