为什么在这个例子中我没有得到 java.util.ConcurrentModificationException ? [英] Why am I not getting a java.util.ConcurrentModificationException in this example?

查看:25
本文介绍了为什么在这个例子中我没有得到 java.util.ConcurrentModificationException ?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:我知道 Iterator#remove() 方法.

Note: I am aware of the Iterator#remove() method.

在下面的代码示例中,我不明白为什么main 方法中的List.remove 会抛出ConcurrentModificationException,但是remove 方法中没有.

In the following code sample, I don't understand why the List.remove in main method throws ConcurrentModificationException, but not in the remove method.

public class RemoveListElementDemo {    
    private static final List<Integer> integerList;

    static {
        integerList = new ArrayList<Integer>();
        integerList.add(1);
        integerList.add(2);
        integerList.add(3);
    }

    public static void remove(Integer toRemove) {
        for(Integer integer : integerList) {
            if(integer.equals(toRemove)) {                
                integerList.remove(integer);
            }
        }
    }

    public static void main(String... args) {                
        remove(Integer.valueOf(2));

        Integer toRemove = Integer.valueOf(3);
        for(Integer integer : integerList) {
            if(integer.equals(toRemove)) {                
                integerList.remove(integer);
            }
        }
    }
}

推荐答案

原因如下:正如 Javadoc 中所说:

Here's why: As it is says in the Javadoc:

该类的迭代器和listIterator返回的迭代器方法是快速失败的:如果列表在任何时候在结构上被修改迭代器创建后的时间,以任何方式,除了通过迭代器自己的 remove 或 add 方法,迭代器会抛出一个并发修改异常.

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.

这个检查是在迭代器的 next() 方法中完成的(你可以从堆栈跟踪中看到).但是只有当 hasNext() 传递 true 时,我们才会到达 next() 方法,这是由 for each 调用以检查是否满足边界的方法.在你的 remove 方法中,当 hasNext() 检查它是否需要返回另一个元素时,它会看到它返回了两个元素,现在删除一个元素后,列表只包含两个元素.所以一切都很顺利,我们已经完成了迭代.不会进行并发修改检查,因为这是在从未调用的 next() 方法中完成的.

This check is done in the next() method of the iterator (as you can see by the stacktrace). But we will reach the next() method only if hasNext() delivered true, which is what is called by the for each to check if the boundary is met. In your remove method, when hasNext() checks if it needs to return another element, it will see that it returned two elements, and now after one element was removed the list only contains two elements. So all is peachy and we are done with iterating. The check for concurrent modifications does not occur, as this is done in the next() method which is never called.

接下来我们进入第二个循环.删除第二个数字后,hasNext 方法将再次检查是否可以返回更多值.它已经返回了两个值,但列表现在只包含一个.但这里的代码是:

Next we get to the second loop. After we remove the second number the hasNext method will check again if can return more values. It has returned two values already, but the list now only contains one. But the code here is:

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

1 != 2,所以我们继续使用 next() 方法,该方法现在意识到有人弄乱了列表并触发了异常.

1 != 2, so we continue to the next() method, which now realizes that someone has been messing with the list and fires the exception.

希望能解决您的问题.

List.remove() 在从列表中删除倒数第二个元素时不会抛出 ConcurrentModificationException.

List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.

这篇关于为什么在这个例子中我没有得到 java.util.ConcurrentModificationException ?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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