Why ConcurrentModificationException occurred only at iterate loop

I wrote two example code as following:

private static class Person
{
    String name;

    public Person(String name)
    {
        this.name = name;
    }
}
public static void main(String[] args)
{
    List<Person> l = new ArrayList<Person>();
    l.add(new Person("a"));
    l.add(new Person("b"));
    l.add(new Person("c"));
    l.add(new Person("d"));


    for(int i  = 0;i<l.size();i++)
    {
        Person s = l.get(i);
        System.out.println(s.name);
        if(s.name.equals("b"))
            l.remove(i);
    }
    System.out.println("==========================");

    for(Person s : l)
        System.out.println(s.name);
}

When I run example code, print on console following result:

a
b
d
==========================
a
c
d

but when I change code as following by a iterate model:

  int i  = 0;
  for(Person s : l)
  {
      if(s.name.equals("b"))
          l.remove(i);
      i++;
  }

I get following result:

a
b
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)

Means of examples are: In traditional loop model ConcurrentModificationException not occurred at traditional for model??

Jon Skeet
people
quotationmark

Yes, in your original for loop you're accessing the value by index - although you should note that you're skipping the check for element c (because by then the value that was at index 2 is now at index 1). There's no way this would create a ConcurrentModificationException, as there's no "context" between accesses - there's nothing to be invalidated when you modify the list.

In the enhanced-for-loop version, you're using an iterator which keeps the context of where you are within the collection. Calling l.remove invalidates that context, hence the error.

You can avoid it by calling remove on the iterator itself:

for (Iterator<Person> iterator = l.iterator(); iterator.hasNext(); ) {
    Person s = iterator.next();
    if (s.name.equals("b")) {
        iterator.remove();
    }
}

people

See more on this question at Stackoverflow