Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
588 views
in Technique[技术] by (71.8m points)

java - magic number of ConcurrentModificationException

I am testing ConcurrentModificationException of collections using code bellow:

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<String>();
    list.add("a");
    list.add("b");
    list.add("c");

    for (String s : list) {
     // if (s.equals("a")) { // ConcurrentModificationException!
        if (s.equals("b")) { // -->> Magic number, NO Exception, Why? 
     // if (s.equals("c")) { // ConcurrentModificationException!
            list.remove(s);
        }
    }
    System.out.println(list);
}

I don't understand why remove "b" is OK, but others NG?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The first thing to know is that (as stated in the JLS) the following enhanced for loop:

for (String s : list) {
    // Do something with s
}

Is equivalent to:

for (Iterator<String> it = list.iterator(); it.hasNext();) {
    String s = it.next();
    // Do something with s
}

If you have a look at the implementation of the iterator in AbstractList, you will see that:

  • hasNext() doesn't check for concurrent modification, and just check if we are at the end of the list, using its size:

    public boolean hasNext() {
            return cursor != size();
    }
    
  • the first thing done by next() is to call checkForComodification() to see if the list was modified while we are iterating:

    public E next() {
            checkForComodification();
        try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
        } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
        }
    }
    
    final void checkForComodification() {
        if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    }
    

So, when you are iterating and removing the penultimate element of your list, the next instruction will be a call to hasNext(), which will return false, because removing one element caused the size of the list to be one less, and your iteration will stop without calling next() and throwing an Exception.

By the way, all of this is just an implementation detail, you should not rely on it as it can change, and use it.remove() to remove an element from the list while you are iterating.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...