我已阅读一篇关于从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);
}
有人能解释一下这段代码中幕后发生的事情吗?
答案 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()
}。您可以尝试调试代码以验证此行为。