Java ConcurrentModificationException在删除两个索引(当前索引和随机索引)时发生

Java ConcurrentModificationException在删除两个索引(当前索引和随机索引)时发生,java,arrays,loops,exception,Java,Arrays,Loops,Exception,我有一份球员名单。 此列表包含没有目标的玩家。目标是指一个玩家以另一个玩家为目标,他们两个都是目标,不应该在列表中 下面循环的目的是在所有玩家之间循环,并搜索目标,如果玩家还没有准备好,它将只调用tick()方法,该方法基本上会勾选目标搜索计时器isReady方法基本上是timer==0 for (Client c : participants) { PlayerTargetDomain dom = c.getTarget(); if (dom.isRea

我有一份球员名单。 此列表包含没有目标的玩家。目标是指一个玩家以另一个玩家为目标,他们两个都是目标,不应该在列表中

下面循环的目的是在所有玩家之间循环,并搜索目标,如果玩家还没有准备好,它将只调用
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
实例不为空,我将使用
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<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();
        }
    }
Iterator itr=participants.Iterator();
while(itr.hasNext()){
客户端c=itr.next();
如果(c!=null){
PlayerTargetDomain dom=c.getTarget();
if(dom.isReady()){
if(dom.getSearchDelay()==0){
共享目标d;
如果((d=搜索(c))!=null){
删除(d.getSecond());
itr.remove();
继续;
}
}
否则{
dom.tickSearchDelay();
}
}
else dom.tick();
}
}

问题在于您在迭代集合时修改了它

至少有两种解决方案

  • 使用索引访问。处理索引会很有趣,因为元素在删除后会移位
  • 收集您需要删除的元素,并在完成迭代后应用所有更改,您会得到很多乐趣,始终记住您处理的元素可以被安排删除
  • 你可以用


    CopyOnWriteArrayList以避免此异常

    您使用迭代器尝试的代码在哪里<代码>迭代器
    可以在迭代时删除元素。出现问题的不是当前索引,而是当您修改其他正在使用的列表时,ConcurrentModificationException。你能给我们看看你在迭代器上使用的实现吗?@JonTaylor添加了迭代器实现,错误显示在itr.remove()行。问题是
    particients.remove(d.getSecond())
    不能以这种方式使用
    迭代器。只有
    it.remove()
    是有效的调用。当存在迭代器(例如用于对集合进行迭代)时,您不能修改集合。集合修改会导致此迭代器被破坏,因此会出现此异常。使用上述形式的for循环编译器为您创建一个迭代器。要解决此问题,您应该为自己创建迭代器并使用它删除项。使用第二个选项。您可以使用CopyOnWriteArrayList和第二个选项,这两个选项都在for循环后删除。@YSBhai那么基本上CopyOnWriteArrayList而不是ArrayList可以解决此问题吗?