Java 带有 ArrayList 的 ConcurrentModificationException

Java ConcurrentModificationException with an ArrayList

我正在使用 Java 创建在线视频游戏。 如果有一个客户端和一个服务器应用程序。 在服务器中,为了处理玩家数据库,我创建了一个名为 inGamePlayers 的 ArrayList,其中包含 Players 对象(具有 InetAdress ipAdress 和 String 用户名)。

当玩家连接时,它首先检查连接的玩家用户名是否== ArrayList 用户名中的玩家之一。如果不是,则将他添加到列表中。否则,连接玩家被认为是 'reconnected'...

当它在 Eclipse 上运行时,它运行起来很奇怪。所以我决定把我的一部分代码作为测试放在 "Java Tutor" 中(这是一个读取你的代码并向你展示变量的网站,当你开始编程时非常方便)。

第一个

for (Player p : inGamePlayers) {

行,它停下来说java.util.ConcurrentModificationException,不是第一次,而是第二次经过。

这是我的全部测试代码

import java.util.ArrayList;

public class YourClassNameHere {

    public static void main(String[] args) {

        ArrayList<Player> inGamePlayers = new ArrayList<Player>();
        inGamePlayers.add(new Player("Griff"));

        String newUsername = "Polak";

        for (Player p : inGamePlayers) {

            if (newUsername == p.username) {
                System.out.println(p.username+" reconnected!");
                break;
            }

            inGamePlayers.add(new Player(newUsername));
        }

        for (Player p : inGamePlayers) {
            System.out.println(p.username);
        }
    }
}

class Player {

    public String username;

    public Player(String username) {
        this.username = username;
    }
}

此代码有多个缺陷。在这种形式中,它将添加新的 Player 实例,直到找到具有匹配名称的条目。如您所见,开始迭代、修改列表并继续迭代将抛出 ConcurrentModificationException。此外,您将字符串与 == 而不是 equals.

进行比较
  for (Player p : inGamePlayers) {

    if (newUsername == p.username) { // This needs to be .equals
      System.out.println(p.username+" reconnected!");
      break;
    }
    // this line runs many times
    inGamePlayers.add(new Player(newUsername));
  }

相反,我建议您将该代码提取到一个新函数中,并更改控制流:

private static void handleConnected(ArrayList<Player> inGamePlayers, String newUsername) {
  for (Player p : inGamePlayers) {
    if (newUsername.equals(p.username)) {
      System.out.println(p.username+" reconnected!");
      return; // return instead of break
    }
  }
  // we did not return, so this user is new
  inGamePlayers.add(new Player(newUsername));
}

// ...

public static void main(String[] args) {
  ArrayList<Player> inGamePlayers = new ArrayList<Player>();
  inGamePlayers.add(new Player("Griff"));

  String newUsername = "Polak";

  // Call this function in place of the old loop
  handleConnected(inGamePlayers, newUsername);

  for (Player p : inGamePlayers) {
    System.out.println(p.username);
  }
}