删除两个索引时的Java ConcurrentModificationException,当前和随机索引

时间:2014-09-02 15:40:18

标签: java arrays loops exception

我有一个球员名单。 此列表包含没有目标的玩家。目标意味着玩家被定位到另一个玩家,他们两个是目标,并且不应该在列表中。

以下循环的目的是遍历所有玩家,并搜索目标,如果玩家尚未准备好,它将只调用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和找到的目标索引对象。

如果SharedTargetDomain中返回的search(Client)实例不为空,我将使用participants

removeAll()列表中删除这两个对象

不幸的是,如果我删除其中任何一个,我将收到以下错误:

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用于当前索引,但我仍然得到错误,因为我也删除了另一个索引,但是如果我删除它,那么另一个与当前索引有什么关系呢?我真的误解了一些事情。

谢谢!

Iterator实施:

    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();
        }
    }

2 个答案:

答案 0 :(得分:3)

问题是你在迭代时修改了集合。

至少有两个解决方案

  1. 使用索引访问权限。处理索引会有很多乐趣,因为删除后元素会被移动。
  2. 收集您需要删除的元素并在完成迭代后应用所有更改,您会获得很多乐趣,始终记住您处理的元素已经安排删除。

答案 1 :(得分:0)

您可以使用

CopyOnWriteArrayList以避免此异常