带迭代器的java.util.concurrentmodificationexception

ktca8awb  于 2021-06-30  发布在  Java
关注(0)|答案(4)|浏览(326)

我知道如果要从集合中删除循环,我会得到以下异常: java.util.ConcurrentModificationException . 但我使用的是迭代器,它仍然会生成这个异常。你知道为什么,怎么解决吗?

HashSet<TableRecord> tableRecords = new HashSet<>();

...

    for (Iterator<TableRecord> iterator = tableRecords.iterator(); iterator.hasNext(); ) {
        TableRecord record = iterator.next();
        if (record.getDependency() == null) {
            for (Iterator<TableRecord> dependencyIt = tableRecords.iterator(); dependencyIt.hasNext(); ) {
                TableRecord dependency = dependencyIt.next(); //Here is the line which throws this exception
                if (dependency.getDependency() != null && dependency.getDependency().getId().equals(record.getId())) {
                    tableRecords.remove(record);
                }
            }
        }
    }
acruukt9

acruukt91#

hashset迭代器的约定是,除了通过spcific迭代器的remove方法之外,不能从hashset中删除。从 dependencyIt ,您删除了一个项目,而不是通过调用其 remove 所以它抛出一个 ConcurrentModificationException .
当记录具有相同的记录id时,似乎要从哈希集中删除记录。重写记录的id不是更容易吗 equals 以及 hashcode 方法以确保具有相同id的记录相等并且具有相同的哈希代码(如果说得通的话(当然)

cmssoen2

cmssoen22#

你必须使用 iterator.remove() 而不是 tableRecords.remove() 只有在使用迭代器中的remove方法时,才能删除对其进行迭代的列表上的项。
编辑:
当您创建迭代器时,它将开始计算应用于集合的修改。如果迭代器检测到某些修改是在没有使用其方法(或在同一集合上使用另一个迭代器)的情况下进行的,它就不能再保证它不会在同一个元素上传递两次或跳过一次,因此它抛出这个异常
这意味着您需要更改代码,以便只通过iterator.remove(并且只使用一个iterator)删除项

列出要删除的项,然后在完成迭代后删除它们。

8ehkhllq

8ehkhllq3#

问题是,在同一时间范围内有两个迭代器,它们相互“争斗”。解决问题的最简单方法是,如果找到匹配项,就跳出内部循环:

for (Iterator<TableRecord> iterator = tableRecords.iterator(); iterator.hasNext(); ) {
    TableRecord record = iterator.next();
    if (record.getDependency() == null) {
        for (Iterator<TableRecord> dependencyIt = tableRecords.iterator(); dependencyIt.hasNext(); ) {
            TableRecord dependency = dependencyIt.next(); //Here is the line which throws this exception
            if (dependency.getDependency() != null && dependency.getDependency().getId().equals(record.getId())) {
                iterator.remove();
                break; // ADD THIS LINE
            }
        }
    }
}

java Iterator 每当在没有使用 Iterator . 你在使用嵌套迭代器,所以 remove() 对其中一个发出的操作将导致另一个抛出 Exception 如果继续使用。因此,如果您需要 remove() ,然后需要在“outer”迭代器上执行此操作(您正在执行此操作),然后停止使用第二个迭代器(添加了 break 语句不存在)。

lrpiutwd

lrpiutwd4#

每次尝试获取下一个元素时,迭代器都会失败快速属性检查底层集合结构中的任何修改。如果发现任何修改,它将抛出concurrentmodificationexception。除了concurrenthashmap和copyonwritearraylist这样的并发集合类之外,集合类中所有迭代器的实现都是设计上很快失败的。
图片来源:谷歌
用一个例子你会更好地理解below:-

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class IteratorExp {
    public static void main(String... q) {
        //CASE - ONE
        List<String> strList = new ArrayList<>(Arrays.asList("a", "b", "c"));
        Iterator<String> itr = strList.iterator();
        /*
         * strList.add("e"); strList.add("f"); strList.add("g");
         */
        while (itr.hasNext()) {
            System.out.println(itr.next());
        }
        /*
         * Exception in thread "main" java.util.ConcurrentModificationException
         * at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at
         * java.util.ArrayList$Itr.next(Unknown Source) at
         * IteratorExp.main(IteratorExp.java:14)
         */

        //CASE - TWO 
        List<Integer> intList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0));
        Iterator<Integer> itrOne = intList.iterator();
        Iterator<Integer> itrTwo = intList.iterator();
        for (; itrOne.hasNext();) {
            if (itrOne.next().equals(5)) {
                itrOne.remove(); // #1
                //intList.remove(itrOne.next()); // #2
            }
        }
        for (; itrTwo.hasNext();) {
            if (itrTwo.next().equals(5)) {
                itrTwo.remove(); // #1
                //intList.remove(itrTwo.next()); // #2
            }
        }

        /*
         * Exception in thread "main" java.util.ConcurrentModificationException
         * at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at
         * java.util.ArrayList$Itr.next(Unknown Source) at
         * IteratorExp.main(IteratorExp.java:35)
         */
    }
}

相关问题