2014-09-02 60 views
1

我有一个球员列表。 此列表包含没有目标的玩家。目标意味着一名玩家瞄准另一名玩家,他们两人是目标,并且不应该在名单中。Java ConcurrentModificationException当删除两个索引,当前和随机一个

以下循环的目的是遍历所有玩家并搜索目标,如果玩家尚未准备好,它只会调用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()

不幸的是,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) { 

为什么我收到THI S'我已经尝试过使用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(); 
     } 
    } 
+0

哪里是你的代码,你有'Iterator'试过吗? '迭代器'工作正常,在迭代时删除元素。 – Braj 2014-09-02 15:42:36

+0

它不是当前索引有问题,当您修改其他某个正在使用的列表时,会发生ConcurrentModificationException。你能告诉我们你使用迭代器的实现吗? – 2014-09-02 15:45:11

+0

@JonTaylor添加了Iterator实现,错误显示在itr.remove()行。 – Artemkller545 2014-09-02 15:47:11

回答

3

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

有至少两个解决方案

  1. 使用索引访问。处理索引会带来很多乐趣,因为元素在移除后会被移位。
  2. 收集您需要在完成迭代后删除并应用所有更改的元素,您总会记住您处理的元素可能已经计划删除,您将获得很多乐趣。
+0

与第二个选项。 – Braj 2014-09-02 15:50:09

+1

可以使用的CopyOnWriteArrayList也 – 2014-09-02 15:50:23

+0

有趣的答案:d:d – 2014-09-02 15:53:34

0

您可以使用

的CopyOnWriteArrayList避免此异常