Unexpected behavior with ArrayList.remove()

I have a pizza code that iterates through a list of objects and checks whether they are colliding or not. If one is collided with, it is removed from the ArrayList.

for (int i = 0; i < arrayList.size(); i++) {
    Object c = arrayList.get(i);
    if (Rect.intersects(foo.getRect(), c.getRect())) { //Android function, checks if the two rectangles are inside each other.
        foo.setPosY(c.getPosY() + 11); // Always works.
        foo.setVelY(bird.getVelY() * -1); // Always works.
        arrayList.remove(i); // Occasionally fails under special circumcisions.
    }
}

When opening the app fresh for the first time this works fine. However, if I exit with the back button and then quickly reopen the app, it will all work except occasionally, removing the object from the ArrayList wont happen.

If I close the app and then remove it from the recent apps list, it works. If I exit with the home key, or the back button and then immediately reopen, it sometimes fails to remove the object. I don't understand why this happens, as everything else still works. The two lines of code just before it function just fine. I just don't get it.

Jon Skeet
people
quotationmark

I suspect the problem is that you're skipping an element after one call to remove, because you're incrementing i and everything in the list is moving up one element. (It's not really clear what the symptoms are at the moment. If this turns out not to be the problem, it's still a problem.)

So if you call remove(2), the next element you want to look at now has index 2.

Common ways of fixing this:

  • Work backwards:

    for (int i = arrayList.size() - 1; i >= 0; i--)
    
  • Use an iterator instead:

    for (Iterator<Foo> iterator = arrayList.iterator(); iterator.hasNext(); ) {
        Foo c = iterator.next();
        if (...) {
            iterator.remove();
        }
    }
    

people

See more on this question at Stackoverflow