【发布时间】:2018-01-25 09:21:58
【问题描述】:
我正在处理的项目有问题。有一个主循环运行程序,每帧调用update() 方法。
我有一个对象是 World,其中包含 HashMap<ChunkPos, Chunk>,其中 ChunkPos 是一个数据结构,它的 xyz 位置代表 Chunk 在 World 中的位置
我试图在我的更新函数中遍历我的世界中的所有块,因为每个块都有自己的 GameObject ArrayList,其中包含这个世界块中的所有对象。
public void update() {
HashMap<ChunkPos, Chunk> chunkMap = world.getChunkMap();
Iterator<Map.Entry<ChunkPos, Chunk>> it = chunkMap.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<ChunkPos, Chunk> item = it.next();
ArrayList<GameObject> chunkObjects = item.getValue().getObjects();
for(GameObject obj : chunkObjects) {
obj.update();
}
}
}
但是,当我运行程序时,我在这一行收到ConcurrentModificationException:
Map.Entry<ChunkPos, Chunk> item = it.next();
我尝试了多种不同的方法来遍历 HashMap,但每次我都会遇到同样的错误。我做错了什么?
如果有帮助,这里是完整的 StackTrace:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
at com.anzanama.lwjgl3d.Game.Game.update(Game.java:40)
at com.anzanama.lwjgl3d.Game.Game.loop(Game.java:31)
at com.anzanama.lwjgl3d.Main.main(Main.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
只是想在此说明一下:我最终实现了一个 WorldChangeScheduler,它会在遍历整个世界并对其进行更新后安排对世界进行的更改。这使它更加健壮,并且具有额外的好处,我可以稍后返回并将这些 WorldChanges 转换为使用我的引擎的其他人可以挂钩的事件。
【问题讨论】:
-
问题不在于对 HashMap 的迭代,而在于您在迭代它时其他事情正在改变地图。同步它或类似的东西。
-
鉴于没有提及线程使用,可能的原因是在调用
obj.update();中您正在修改HashMap。除非通过迭代器本身进行,否则在迭代集合时不能修改集合
标签: java hashmap iteration nested-lists