-1

I understand that when using foreach loops or iterators, and removing elements from a list while iterating through it, it can cause the error by confusing the iterator. however I don't seem to be able to visualize how it can confuse it. And thus Im wondering if someone could explain to me how it can confuse an iterator? Thanks

1List<Integer> l3 = new ArrayList<>();
2 l3.add(0); l3.add(2); l3.add(3); l3.add(5);
3
4 int i = 0;
5 for (int e : l3) {
6 if (e % 2 == 0) l3.remove(i);
7 
8 }else{ i++};

I expect this to remove all even numbers and remain behind odd numbers, but i am told this could give a concurrentModificationError.

  • Please don't add line numbers, they get in the way when someone tries to copy & paste your code to try it. See [mcve], btw. That said, the iterator has to remember its position in the list, and if you modify the list, how is the iterator supposed to know where to continue? This may be simple if you remove only one element, but what about multiples? – Robert May 02 '23 at 20:52
  • I figured it just continues to iterate trough the values it had initially, in other words, just move onto the next. – Nadeem Hussain May 02 '23 at 20:54
  • the `for` loop is using an `Iterator` from the list - if the list is changed after the iterator is created (without using the iterators own methods) it will throw that exception - The iterator is [fail-fast](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/ArrayList.html#fail-fast) (the first two paragraphs) – user16320675 May 02 '23 at 21:06

1 Answers1

1

You are removing an element from the list using

if (e % 2 == 0) l3.remove(i);

while at the same time, iterating with an iterator here

for (int e : l3) {

So the list contents and size are out of sync with the iterator causing the exception to be thrown. You should explicitly create an iterator and use that for removal.

List<Integer> l3 = new ArrayList<>();
l3.add(0); l3.add(2); l3.add(3); l3.add(5);

Iterator<Integer> it = l3.iterator();
while (it.hasNext()) {
    int v = it.next();
    if (v % 2 == 0) {
        it.remove();
    }
}
System.out.println(l3);

prints

[3, 5]

Or without using an iterator or explicit loop, use removeIf

l3.removeIf(item -> item % 2 == 0);
WJS
  • 36,363
  • 4
  • 24
  • 39