首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >带迭代器的java.util.ConcurrentModificationException

带迭代器的java.util.ConcurrentModificationException
EN

Stack Overflow用户
提问于 2013-06-06 22:58:43
回答 3查看 41.4K关注 0票数 31

我知道如果试图通过简单的循环从集合中删除,我会得到这个异常:java.util.ConcurrentModificationException。但是我正在使用Iterator,它仍然会生成这个异常。你知道为什么和如何解决它吗?

代码语言:javascript
复制
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);
                }
            }
        }
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-06-06 23:01:23

您必须使用iterator.remove()而不是tableRecords.remove()

只有在使用迭代器中的remove方法时,才能移除要迭代的列表上的项。

编辑:

当您创建迭代器时,它开始计算应用于集合的修改。如果迭代器检测到某些修改是在未使用其方法(或使用同一集合上的另一个迭代器)的情况下进行的,则它不能再保证不会在同一元素上传递两次或跳过一次,因此抛出此异常

这意味着你需要修改你的代码,这样你只需要通过iterator.remove (并且只有一个迭代器)移除项目。

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

票数 48
EN

Stack Overflow用户

发布于 2013-06-06 23:01:56

hashset迭代器的约定是,除非通过特定迭代器的remove方法,否则不能从哈希集删除。从dependencyIt的角度来看,您已经移除了一个项,而不是通过调用它的remove方法来使其抛出ConcurrentModificationException

当它们具有相同的记录id时,您似乎想从您的hashset中删除记录。重写记录的equalshashcode方法以确保具有相同id的记录相等并且具有相同的哈希码,不是更容易吗?(当然,如果这有意义的话)

票数 0
EN

Stack Overflow用户

发布于 2013-06-06 23:06:29

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

代码语言:javascript
复制
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(),那么您将需要在“外部”迭代器(您正在做的)上执行该操作,并在之后停止使用第二个迭代器(添加的break语句就是这样做的)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16965484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档