神圣的ConcurrentModificationException数 [英] magic number of ConcurrentModificationException

查看:84
本文介绍了神圣的ConcurrentModificationException数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码测试 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);
}

我不明白为什么删除b没关系,但其他人NG ?

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

推荐答案

首先要知道的是(如 JLS )以下增强版for循环:

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
}

相当于:

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

如果你看看在 AbstractList 中执行迭代器,你会看到:

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


  • hasNext()不检查并发修改,只是检查我们是否在列表末尾,使用其大小:

  • 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();
}


  • 下一步做的第一件事( )是在我们迭代时调用 checkForComodification()来查看列表是否被修改:

  • 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();
    }
    


  • 所以,当你正在迭代并删除列表的倒数第二个元素,下一条指令将是对 hasNext()的调用,它将返回 false ,因为删除一个元素导致列表的大小减少一个,并且您的迭代将停止而不调用 next()并抛出异常

    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.

    顺便说一句,所有这些只是一个实现细节,你不应该依赖它,因为它可以改变,并且使用 it.remove() 在迭代时从列表中删除元素。

    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.

    这篇关于神圣的ConcurrentModificationException数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆