Java 无法在数组列表中存储对象

Java can't store Object in arraylist

基本上,我正在用 MVC 制作 yahtzee 游戏。它工作正常,但是当我尝试保存游戏会话时,它不会保存包含玩家数组列表的游戏对象。这不会停止执行,这肯定会清除游戏数组列表。 基本上,游戏实例具有以下字段:

public String name;
public int numberOfPlayers;
public ArrayList<Player> players = new ArrayList<>();
int playerListIndex;
ArrayList<Boolean> checkable;
StandardRules yahtzeeRule = new StandardRules();
public int rounds;
public String date;

玩家的 Arraylist 包含对象 Player 的实例,它有自己的字段和 gettters/setters。

当我调用方法时,我设法跟踪到不保存的问题:

public void saveGame(Game thisGame) {
    DB.saveGame(thisGame);
}

依次调用 class:

public class DB {

private static ArrayList<Game> savedGames = new ArrayList<>();

/**
 * Saves the passed member into the database.
 * @param game, the member to be saved.
 */
public static void saveGame(Game game) {
    for (Game g : savedGames) {
        if (g.name.equals(game.name)) {
            savedGames.remove(g);
            savedGames.add(game);
        }
        else {
            savedGames.add(game);
        }
    }
}    

saveGame 方法主要检查已保存游戏的 Arraylist 是否存在该名称,如果存在,则删除旧游戏并添加新游戏。如果没有该名称的游戏,它只是将游戏添加到列表中。 (我可能稍后会实现一个 MYSQL 数据库,但为了确保程序首先运行,我想使用 arraylist 来测试东西)

我的印象是我需要对数据库进行静态引用,以确保我一直尝试访问同一个数据库,而不是混淆数据库的实例。

我做错了什么?

尝试遵循逻辑。您正在遍历数组以保存游戏。如果数组为空,您希望发生什么?如果 Array 有六个元素,你希望这个列表中有什么?此外,如果使用列表中已有的名称执行此循环,您很可能 运行 进入 ConcurentModificationException。您可能希望遍历 List 并将副本存储到变量中。但是不要在循环中进行保存和删除。

所以最后你的问题是你在空列表上循环以保存 Game,这实际上是行不通的,因为你的 List 是空的,你永远不会到达那个部分在 List.

中添加内容

您很可能想要这样的解决方案来将游戏存储在 List

public static void saveGame(Game game) {
    Game dupGame = null;
    for (Game g : savedGames) {
        if (g.name.equals(game.name)) {
            dupGame = g;
        }
    }
    if (dupGame != null) {
        savedGames.remove(dupGame );
    }
    savedGames.add(game);
}

编辑:

您还可以使用 Map,这将使查找重复项等更快更容易。

public class DB {

    private static Map<String,Game> savedGames = new HashMap<>();

    /**
     * Saves the passed member into the database.
     * 
     * @param game
     *            , the member to be saved.
     */
    public static void saveGame(Game game) {
        savedGames.put(game.name.toLowerCase(), game);
    }
}

您的方法可以 return 异常,因为您从 ArrayList 中读取内容并在 loop 中添加内容。

试试这个。 :)

for(Game g : savedGames) {
    if(g.name.equals(game.name)) {
        savedGames.remove(g);
        savedGames.add(0, game);
    } else {
        savedGames.add(0, game);
    }
}

您想将这些已保存的游戏正确地保存在内存中。将它们设为静态没有问题。您遇到的唯一问题是您正在遍历 savedGames 列表并修改它以添加和删除少数游戏。这是错误的。它可能会给你并发更新异常。

public class DB {

    private static ArrayList<Game> savedGames = new ArrayList<>();

    /**
     * Saves the passed member into the database.
     * @param game, the member to be saved.
     */
    public static void saveGame(Game game) {
          boolean exists=false;
          boolean removalObject=null;
          for (Game g : savedGames) {
            if (g.name.equals(game.name)) {
                exists=true;
                removalObject=g;
            }
        }
        savedGames.add(removalObject);
        savedGames.add(game);
    }
}

第一个问题是,尝试将游戏添加到空的 ArrayList 将失败,因为添加操作是在循环内完成的,如果 savedGames 为空,则永远不会 运行。如果 Object class 的 equals(Object obj) 在游戏 class 中被正确覆盖,remove(Object obj) 方法也会按预期工作。 试试下面这个... 覆盖游戏中的 equal() 方法 Class:

@Override
public boolean equals(Object obj) {
    if(obj != null && obj instanceof Game){
        Game gameObj = (Game)obj;
        if(this.name.equals(gameObj.name)){
            return true;
        }
    }
  return false;
}

按如下方式执行 saveGame() 方法:

public static void saveGame(Game g){
    if(games.contains(g)){
        games.remove(g);
    }
    // Add the game after removing the existing 
    // or if never existed
        games.add(g);
}