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

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

问题描述

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

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

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

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

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



$ b 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);



$ b $ / code $ / pre

解决方案

下面是为什么:
就像在Javadoc中说的那样:
$ b


这个类的迭代器和listIterator
方法是快速失败的:如果在迭代器创建后的任何
时间结构上修改列表,除了通过
迭代器自己的remove或add方法,迭代器将抛出一个
的ConcurrentModificationException。

这个检查在 next 迭代器的方法(正如你可以看到的堆栈跟踪)。但是,只有当 hasNext()传递为true时,我们才能到达 next()方法,这就是为每个检查是否满足边界。在你的remove方法中,当 hasNext()检查是否需要返回另一个元素时,它会看到它返回了两个元素,现在只有一个元素被移除包含两个元素。所以,一切都很好,我们完成迭代。检查并发修改不会发生,因为这是在 next()方法中完成的,永远不会调用。



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

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



$ b $ 1 $ = 2,所以我们继续 next()方法,它现在意识到有人已经搞乱了列表并触发了异常。



希望清除你的问题。

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

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

解决方案

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

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.

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.

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, so we continue to the next() method, which now realizes that someone has been messing with the list and fires the exception.

Hope that clears your question up.

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

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