集合删除方法不会给出并发修改异常

时间:2014-05-07 06:52:59

标签: java collections

我已阅读一篇关于从this link

中删除收藏中元素的文章

根据我的理解迭代器删除方法防止并发修改异常然后删除Collection.But的方法当我尝试运行下面的codde我无法得到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);
}
  • 根据javadoc,当我们尝试在iteartion期间进行任何修改时抛出ConcurrentModicationException。我正在使用集合remove方法,但仍然没有异常。但是如果我注释行 dayList.remove(“Tuesday”) ; ,抛出异常。

有人能解释一下这段代码中幕后发生的事情吗?

3 个答案:

答案 0 :(得分:3)

无法保证迭代器的快速失败行为。失败快速迭代器会尽最大努力抛出ConcurrentModificationException。迭代器可能会也可能不会检测到无效的使用情况。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应仅用于检测错误。

答案 1 :(得分:2)

如果我评论行dayList.remove(“Tuesday”);,则抛出异常....

实际上这不是问题。问题是仅针对中间值发生异常。

每个'循环的

'的工作原理如下,

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

重复步骤2和3,直到hasNext()返回false。

如果我们从列表中删除一个元素,它的大小会减少并且modCount会增加。

如果我们在迭代时删除一个元素,则modCount!= expectedModCount会被满足并抛出ConcurrentModificationException。

但删除第二个最后一个对象很奇怪。让我们看看它是如何工作的。

最初,

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.

在你删除'd'的情况下,大小会减少到4。

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

在其他情况下,将抛出ConcurrentModificationException as modCount!= expectedModCount。

在这种情况下,不会进行此项检查。

如果您尝试在迭代时打印元素,则只会打印四个条目。跳过最后一个元素。

您的问题类似于this问题。

答案 2 :(得分:1)

添加一个Thursday,您将再次开始获取异常:)

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

所以基本上是因为无法保证迭代器的快速失败行为。失败快速迭代器会尽最大努力抛出ConcurrentModificationException。查看documentation here

编辑:您的情况不会引发异常,因为在以下代码中:

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

正在删除第二个最后一个元素,实际上会将大小或dayList 3 更改为 2 。因此itr.hasNext()false从列表中删除后返回Monday,因此不会进入最后一个条目的循环,即Wednesday,并避免调用itr.next() }。您可以尝试调试代码以验证此行为。

相关问题