I am trying to remove items from an array list with an iterator and I keep getting the ConcurrentModificationException
here is my code:
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();
}
}
}
it works for about the first 15 to 20 times and then I get the error every couple clicks
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)
I am not entirely sure which one throws the errors
Your get a ConcurrentModificationException
because you remove an element from a collection while you are iterating over that collection, other than via the iterator. In this case, you have no explicit iterator for the outer iteration, so there is no way to safely modify the sprites
collection inside the loop.
The best you can do is probably to collect the elements to delete into a temporary collection, then remove them all after the loop, something like this:
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);