我有一份球员名单。 此列表包含没有目标的玩家。 Targets 表示一个玩家针对另一个玩家,他们两个是目标,不应该在列表中。
下面这个循环的目的是遍历所有玩家,寻找目标,如果玩家还没有准备好,就调用tick()
方法,基本上勾选目标搜索计时器。 isReady
方法基本上是 timer == 0
for (Client c : participants) {
PlayerTargetDomain dom = c.getTarget();
if (dom.isReady()) {
if (dom.getSearchDelay() == 0) {
SharedTargetDomain d;
if ((d = search(c)) != null) {
participants.removeAll(Arrays.asList(d.getFirst(), d.getSecond()));
continue;
}
}
else {
dom.tickSearchDelay();
}
}
else dom.tick();
}
现在的 search() 方法,基本上是寻找匹配的目标,如果找到,它将构建包含当前索引和找到的目标索引对象的 SharedTargetDomain
。
如果 search(Client)
返回的 SharedTargetDomain
实例不为空,我将从 participants
列表中删除这两个对象,使用全部移除()
不幸的是,如果我删除其中任何一个,我将收到以下错误:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at mod.game.TargetManager.execute(TargetManager.java:24)
第 24 行是这样的:
for (Client c : participants) {
为什么我会收到这个?我已经尝试对当前索引使用迭代器,但我仍然收到错误,因为我也在删除另一个索引,但是如果我删除另一个索引,另一个与当前索引有什么关系呢?我真的误会了什么。
谢谢!
迭代器
实现:
Iterator<Client> itr = participants.iterator();
while(itr.hasNext()) {
Client c = itr.next();
if (c != null) {
PlayerTargetDomain dom = c.getTarget();
if (dom.isReady()) {
if (dom.getSearchDelay() == 0) {
SharedTargetDomain d;
if ((d = search(c)) != null) {
participants.remove(d.getSecond());
itr.remove();
continue;
}
}
else {
dom.tickSearchDelay();
}
}
else dom.tick();
}
}
最佳答案
问题是您在迭代时修改集合。
至少有两种解决方案
- 使用索引访问。处理索引会带来很多乐趣,因为元素会在删除后移动。
- 收集您需要删除的元素并在完成迭代后应用所有更改,始终牢记您处理的元素可能已经安排删除,您会得到很多乐趣。
关于删除两个索引时的Java ConcurrentModificationException,当前索引和随机索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25627273/