java.util.ConcurrentModificationException 使用正确的 remove() 方法时显示

java.util.ConcurrentModificationException displaying when using the correct remove() method

我正在尝试在 isActive 为 false 时删除实体。当实体属性 isActive 设置为 false 时,它​​进入 if 语句并删除实体,然后再次遍历实体列表然后崩溃。根据我的研究,我正在使用正确的方法从数组列表中删除对象。

删除实体并遍历列表时的代码是

    for (Entity entity : entities) {// itaarate through all the entities in list of entities

        entity.render(shader, camera, this);// render each entity

        if (!entity.isActive())// checks if entity attribute is active
            entities.remove(entity);// removes entity from list

    }

在从列表中删除实体后使用调试器时,它会返回到 for 循环的顶部,然后显示此页面

调试时的变量window

控制台中显示的完整错误是

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at project.World.render(World.java:196)
at project.Main.<init>(Main.java:152)
at project.Main.main(Main.java:167)

正在创建的列表是

public static ArrayList<Entity> entities; // contains all entities

迭代时不能更改集合。

List<Entity> entitiesToRemove = new ArrayList<>();

for (Entity entity : entities) {
    entity.render(shader, camera, this);

    if (!entity.isActive()) {
        entitiesToRemove.add(entity);
    }
}

entities.removeAll(entitiesToRemove);

java.util.ConcurrentModificationException displaying when using the correct remove() method

其实你用错了方法。或者更准确地说,错误对象上的 remove() 方法。

您可以在迭代时删除一个元素...但是您需要在 Iterator 对象上使用 remove() 方法;有关详细信息,请参阅 javadoc

Iterator<Entity> it = entities.iterator();
while (it.hasNext()) {
    Entity entity = it.next();
    entity.render(shader, camera, this);

    if (!entity.isActive()) {
        it.remove();
    }
}

请注意 Iterator.remove() 是一个可选操作,但 ArrayList 迭代器确实实现了它。

ListIteratorAPI方法相同,但Iterator更通用。 (您可以将上述示例代码用于任何可以用 Iterator 迭代的类型,而不仅仅是 List 类型。)

来自 official java list tutorial

for (ListIterator<E> it = list.listIterator(); it.hasNext();) {
    if (val == null ? it.next() == null : val.equals(it.next())) {
        it.remove();
    }
}

根据您的代码调整示例:

for (ListIterator<Entity> it = entities.listIterator(); it.hasNext();) {
    Entity entity = it.next();
    entity.render(shader, camera, this);    
    if (entity.isActive()) {
        it.remove();
    }
}