Question

I have read an article regarding removing elements from Collections from this link

As per my understanding iterator remove method prevents Concurrent modification exception then remove method of Collection.But when i try to run the below codde i am unable to get concurrentmoficationexception

     List dayList= new ArrayList();
     dayList.add("Sunday");
     dayList.add("Monday");
     dayList.add("Tuesday");
     dayList.add("Wednesday");
     dayList.remove("Tuesday");
     Iterator itr=dayList.iterator();
        while(itr.hasNext())
        {
           Object testList=itr.next();
           if(testList.equals("Monday"))
             {
            dayList.remove(testList);

             }
    }
    System.out.println(dayList);
}
  • As per javadoc the ConcurrentModicationException is thrown when we try to do any modification during iteartion.I am using collections remove method,but still there is no exception.But if I comment line dayList.remove("Tuesday");,exception is thrown.

Can anyone explain what is happening behind the scene in this code?

Was it helpful?

Solution 2

if I comment line dayList.remove("Tuesday");,exception is thrown....

Actually this is not problem here. Problem is exception is occurring for middle value only.

‘for each’ loop works as follows,

1.It gets the iterator.
2.Checks for hasNext().
public boolean hasNext() 
{
      return cursor != size(); // cursor is zero initially.
}
3.If true, gets the next element using next().

public E next() 
{
        checkForComodification();
        try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
        } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
        }
}

final void checkForComodification() 
{
    // Initially modCount = expectedModCount (our case 5)
        if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

Repeats steps 2 and 3 till hasNext() returns false.

In case if we remove an element from the list , it’s size gets reduced and modCount is increased.

If we remove an element while iterating, modCount != expectedModCount get satisfied and ConcurrentModificationException is thrown.

But removal of second last object is weird. Lets see how it works in your case.

Initially,

cursor = 0 size = 5 --> hasNext() succeeds and next() also succeeds without exception.
cursor = 1 size = 5 --> hasNext() succeeds and next() also succeeds without exception.
cursor = 2 size = 5 --> hasNext() succeeds and next() also succeeds without exception.
cursor = 3 size = 5 --> hasNext() succeeds and next() also succeeds without exception.

In your case as you remove ‘d’ , size gets reduced to 4.

cursor = 4 size = 4 --> hasNext() does not succeed and next() is skipped.

In other cases, ConcurrentModificationException will be thrown as modCount != expectedModCount.

In this case, this check does not take place.

If you try to print your element while iterating, only four entries will be printed. Last element is skipped.

Your question is similar to this question.

OTHER TIPS

The fail-fast behavior of an iterator cannot be guaranteed. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. The iterator may or may not detect the invalid usage. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

Well add a Thursday and you would start getting the exception again :)

List dayList= new ArrayList();
dayList.add("Sunday");
dayList.add("Monday");
dayList.add("Tuesday");
dayList.add("Wednesday");
dayList.add("Thursday");    // Added by Kuldeep
dayList.remove("Tuesday");
Iterator itr=dayList.iterator();
while(itr.hasNext())
{
    Object testList=itr.next();
    if(testList.equals("Monday"))
    {
        dayList.remove(testList);
    }
}
System.out.println(dayList);

So essentially that is because The fail-fast behavior of an iterator cannot be guaranteed. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Look at the documentation here.

EDIT : The exception is not thrown in your case is because in the following code:

    if(testList.equals("Monday"))
    {
        dayList.remove(testList);
    }

you are removing the second last element, which actually change the size or the dayList from 3 to 2. So the itr.hasNext() returns false after Monday is removed from the list and hence does not go into the loop for last entry i.e. Wednesday and avoids the call to itr.next(). You may try debugging the code to verify this behavior.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top