如何避免ConcurrentModificationException

时间:2014-10-17 19:33:50

标签: java iterator concurrentmodification

我正在尝试使用迭代器从数组列表中删除项目,并且我继续获取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 个答案:

答案 0 :(得分: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);