java - List 抛出 ConcurrentModificationException 但 set 不抛出 ConcurrentModificationException?

标签 java list arraylist set hashset

<分区>

我有下面两个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 类中,相同的逻辑由集合系列执行。

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

没有任何ConcurrentModificationException

我只是想知道为什么在 list 系列的情况下,同一段代码会抛出 ConcurrentModificationException,但没有任何 ConcurrentModificationException 以防万一集合

最佳答案

这是一种“逆行”行为,因为迭代器一旦完全遍历,就不可重用,也就是当您到达列表末尾时,它们的 hasNext 方法应该返回 false。

虽然在这种情况下,ArrayList.iterator返回的迭代器是一个内部实现类,hasNext的代码如下:

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

因此,当您在第二个循环中调用 hasNext 时,它(错误地)表明有更多项需要迭代,因为您在第一个循环之后执行了一个更改列表大小的操作迭代。从语义上讲,您不应该在到达列表末尾后继续迭代列表中的项目,但是由于这个实现细节,它允许您继续第二个 while 循环。当然,此时,由于您在支持列表中所做的更改,您会得到并发修改异常。

另一方面,您的哈希集使用的迭代器的 hasNext 实现如下:

public final boolean hasNext() {
    return next != null;
}

此实现恰好不会在迭代完成后对哈希集所做的修改“脆弱”,因此 hasNext 方法表现得更好。

关于java - List 抛出 ConcurrentModificationException 但 set 不抛出 ConcurrentModificationException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15091937/

相关文章:

python - 在Python中从列表中随机选择时是否加载了所有方法的值?

python - 如何计算列表列表中存在的重复项目?

python - 合并长度大于2的字典列表元素

java - 如何使用 RxJava2 过滤 Arraylist

java - JPA 多线程添加如果不存在?

java - 如何检查 DirectedSparsedGraph 是否包含具有这 2 个节点的节点之间的边?

c# - 将 Java WebService 的 Java Arraylist 返回转换为 C# Arraylist

从点的数组列表中进行java圆识别

java - Spring MVC 中特定路径变量的可能值列表

java - 如何使用 Slick2D 渲染最后一个字符字形的一部分