我有以下两个java类
import java.util.*;
public class ArrayListTest032 {
public static void main(String[] ar) {
List<String> list = new ArrayList<String>();
list.add("core java");
list.add("php");
list.add("j2ee");
list.add("struts");
list.add("hibernate");
Iterator<String> itr = list.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
list.remove("php");
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
}
当我运行上面的代码时,我得到下面的输出。
core java
php
j2ee
struts
hibernate
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at ArrayListTest032.main(ArrayListTest032.java:20)
这是预期的,因为我在迭代时修改列表。但在下面的java类中,相同的逻辑是由set family执行的。
import java.util.*;
public class HashSetTest021 {
public static void main(String[] ar) {
Set<String> set = new HashSet<String>();
set.add("core java");
set.add("php");
set.add("j2ee");
set.add("struts");
set.add("hibernate");
Iterator<String> itr = set.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
set.remove("php");
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
}
输出是。
hibernate
core java
j2ee
php
struts
没有任何并发修改异常.
我只是想知道为什么同一段代码会抛出并发修改异常的情况下list
家人,但没有任何人并发修改异常的情况下set
family
这是一种“倒退”行为,因为迭代器一旦完全遍历,就不可重用,也就是它们的hasNext
当到达列表末尾时,方法应该返回 false。
但在这种情况下,迭代器返回ArrayList.iterator
是一个内部实现类,代码为hasNext
如下:
public boolean hasNext() {
return cursor != size;
}
所以当你打电话时hasNext
在第二个循环中,它指示(错误地)有更多项目需要迭代,因为您在第一次迭代后执行了更改列表大小的操作。从语义上讲,在到达列表末尾后,您不应该能够继续迭代列表中的项目,但由于此实现细节,它允许您继续执行第二个 while 循环。当然,此时,由于您在支持列表中所做的更改,您会遇到并发修改异常。
另一方面,哈希集使用的迭代器有其hasNext
实施如下:
public final boolean hasNext() {
return next != null;
}
这种实现恰好不会因为迭代完成后对哈希集所做的修改而“脆弱”,因此hasNext
方法表现更好。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)