我对Iterator在主要类上的不同行为提出了一些问题(不仅仅是针对List类)。
如果我为-每一个写-我将有一个例外:
Collection<String> cc= new ArrayList<>(3);
cc.add("Cio");
cc.add("Mio");
cc.add("Tio");
for (String s:cc) {
System.out.println(s);
cc.remove(s); //Exception
}如果我使用Iterator,我也不会有例外:
for (Iterator<String> it =cc.iterator(); it.hasNext();) {
String s =it.next();
if (s.startsWith("C"))
it.remove();
}这对于ArrayDeque来说是不同的,事实上,如果我使用-每一个,我也不会有一个例外:
ArrayDeque<String> greetings = new ArrayDeque<String>();
greetings.push("hello");
greetings.push("hi");
greetings.push("ola");
greetings.pop();
greetings.peek();
while (greetings.peek() != null)
System.out.print(greetings.pop());但是,如果我使用迭代器,我将有一个例外:
Iterator<String> it = greetings.iterator();
while(it.hasNext()) {
System.out.println(greetings.pop()); //Exception
}为什么?迭代器是否为其他JFC集合抛出异常,特别是: HashSet、TreeSet、LinkedList?
非常感谢!
一个。
发布于 2019-04-06 14:51:13
ArrayList
列表维护一个modCount字段,该字段每次对列表进行结构修改时都会递增。
结构修改是那些改变列表大小的修改,或者以其他方式干扰它,以致正在进行的迭代可能产生不正确的结果。
更远..。
如果该字段的值意外更改,则迭代器(或列表迭代器)将抛出一个ConcurrentModificationException,以响应下一个操作、删除、前一个操作、设置或添加操作。这提供了快速失败的行为,而不是在此字段的iteration.Use中由子类进行并发修改时的非确定性行为是可选的。 如果一个子类希望提供快速失败的迭代器(和列表迭代器),那么它只需要在其add(int,E)和remove(int)方法中增加这个字段(以及它覆盖导致对列表进行结构修改的任何其他方法)。
列表迭代代码的两个部分:
1.
for (String s:str1) {
System.out.println(s);
str1.remove(s);
}和
2.
Iterator<String> i1 = str.iterator();
while(i1.hasNext()) {
i1.next();
i1.remove();
}-看上去可能是一样的,但内部却有点不同。
值得一提的是,列表的迭代器保持一个expectedModCount。在迭代时修改列表时,这应该与modCount同步。
在第一种情况下,String s:str1获取迭代器,检查hasNext()并调用next(),就像在第二种情况下一样。不同之处在于remove()方法调用。str1.remove(s);调用ArrayList的remove方法。这会增加modCount,但不会增加expectedModCount。因此,在第二次迭代中,当调用next()时,它会抛出ConcurrentModificationException。另一方面,在第二种情况下,i1.remove();在ArrayList中调用Iterator实现中的remove方法。这增加了modCount和expectedModCount以及--宾果。
注意:在第二个场景中缺少i1.next();将导致IllegalStateExcepton。这是因为列表中下一个元素的游标没有更新。
TakeAway:在迭代列表时不调用list.remove(element)方法。此方法用于在不进行迭代时调用。
ArrayDeque
如果您像这样迭代ArrayDeque:
Iterator<String> i1 = str.iterator();
while(i1.hasNext()) {
i1.next();
i1.remove();
}--它的工作方式与ArrayList完全相同.
当调用pop()或ArrayDeque类的push()方法时,实际上并不迭代队列,只需修改队列的头或尾。这就像在不进行迭代时调用ArrayList类的remove()方法一样(不是ArrayList的Iterator的remove() )。这不符合结构调整的条件。所以它不会抛出异常。
请参阅这文章。
https://stackoverflow.com/questions/55549414
复制相似问题