2

I have tried the following two scenarios:

    ArrayList arrayList = new ArrayList();
    arrayList.add("1");
    arrayList.add("2");
    arrayList.add("3");

    Iterator iterator = arrayList.iterator();
    while (iterator.hasNext()) {

        String value = (String) iterator.next();
        System.out.println("---->" + value);
        if (value.equals("1")) {
            arrayList.remove(0);
        }
    }

The first scenario output is :

---->1
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at Test.main(Test.java:83)

Probably the ConcurrentModificationException exception is caused because I'm trying to modify the collection while I'm still iterating it.

In the second scenario I changed the if() condition from value.equals("1") to value.equals("2") and the program does not throw any error.

ArrayList arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");

Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {

    String value = (String) iterator.next();
    System.out.println("---->" + value);
    if (value.equals("2")) {
        arrayList.remove(0);
    }
}

The second scenario output is:

---->1
---->2

In both the scenarios, my program does not reach the 3rd element (Value : 3).

Can you please help me to understand the problem ?

acornagl
  • 521
  • 5
  • 24
Keval Pithva
  • 600
  • 2
  • 5
  • 21
  • 1
    `arrayList.remove(0);` is your problem here. Use the `iterator` object to remove elements instead. – JonK Dec 09 '16 at 12:27
  • @Jonk I know it will avoid error by calling remove method of iterator object. But I want to understand why it is not reached at 3rd element in second scenario? – Keval Pithva Dec 09 '16 at 12:30
  • It's because after deleting at index 0 the element `3` becomes second so is already considered iterated over; it will not throw an exception because the fail-fast behavior is not guaranteed - see the possible duplicate. – Jiri Tousek Dec 09 '16 at 12:35

5 Answers5

4

Problem is you are removing element from the list which presend at index 0. Instead of removing from the list use iterator.remove() method. For more info read this.

program code -

List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");

Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
   String value = (String) iterator.next();
   System.out.println("---->" + value);
   if (value.equals("2")) {
      iterator.remove();
   }
}

Why list not returning the last element?

Answer -

you are removing element from the list and you already perform iterator action against same list. At the end iterator.hasnext() method returns false so you are not getting last element.

If you want to see it for demo purpose run below sample codes -

List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
    String value = (String) iterator.next();
    System.out.println("---->" + value);
    if (value.equals("2")) {
       arrayList.remove(0);
    }
}
System.out.println("ArrayList : "+arrayList);

output -

---->1

---->2

ArrayList : [2, 3]

List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");

Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
      String value = (String) iterator.next();
      System.out.println("---->" + value);
      if (value.equals("2")) {
         iterator.remove();
      }
}
System.out.println("ArrayList : "+arrayList);

output -

---->1

---->2

---->3

ArrayList : [1, 3]

ketan
  • 2,732
  • 11
  • 34
  • 80
  • I know it will avoid error by calling remove method of iterator object. But I want to understand why it is not reached at 3rd element in second scenario? – Keval Pithva Dec 09 '16 at 12:31
  • 1
    @Keval Pithva- Becase you are removing element from the list and you already perform iterator action against same list. At the end iterator.hasnext() method returns false so you are not getting last element. – ketan Dec 09 '16 at 12:34
1

I suppose that you encounter the problem only in the first case because you are trying to remove the element pointed by the iterator. In fact, the second scenario succeeds because you remove the first arraylist element that, at that moment, is not pointed by the iterator.

(p.s. I agree with all the various and future answers that will describe you how to solve your problem by showing fragments of code, I just provided you an explanation of what happens)

acornagl
  • 521
  • 5
  • 24
1

The ConcurrentModificationException occurs because you are removing the same element (at index 0) that the current iteration of the loop is reading (the one with value = ”1”). In the second case you don't see the exception because you are removing the element at index 0, but are reading the element at index 1 (the one with value = "2"). You cannot remove an element concurrently while reading it unless you use one of the collections that supports concurrency (see java.util.concurrent package)

You are removing an element (remove(0)) while iterating the list, which "shifts the end of the list" towards left by one. So, the next time you check for iterator.hasNext(), it will return false and the original 3rd element never gets processed.

Kartik Pandya
  • 2,718
  • 2
  • 14
  • 28
1

By running two pieces of code in debug mode, I found the following.

1st scenario:

Elements saved from arraylist:

Elements saved from arraylist

After the remove command has been executed:

The ConcurrentModificationException gets thrown at the following line

String value = (String) iterator.next();

2nd Scenario:

The ArrayList will be the same as the second link.

After printing 2, the control breaks from

while (iterator.hasNext())

as iterator.hasNext() = null. Hence it's safe.

denvercoder9
  • 2,979
  • 3
  • 28
  • 41
Isha Agarwal
  • 420
  • 4
  • 12
0

When you iterate on a Collection, you should remove the element with the iterator :

iterator.remove()

In the second code, here :

    if (value.equals("2")) {
        arrayList.remove(0);
    }

you remove the first element of the list. The list has so a size of 2 elements.
The iterator implementation takes into consideration the size of the list to know if it has next elements or not :

public class ArrayList<E> extends AbstractList<E>
   ...
  private class Itr implements Iterator<E> {

  public boolean hasNext() {
      return cursor != size;
  }
}

Since two elements were iterated and that the list has now a size of 2 because you remove one element of it, the iterator considers that it has not next element to iterate on.

If you use an iterator to remove the current element, you have not this side-effect.

davidxxx
  • 125,838
  • 23
  • 214
  • 215