Java не может хранить объект в массиве

По сути, я делаю игру на яхтах в MVC. Он отлично работает, но когда я пытаюсь сохранить сеанс игры, он не сохраняет игровой объект, содержащий и список игроков. Это без остановки выполнения, которое, безусловно, очистит список игр. По сути, экземпляр игры имеет следующие поля:

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, который имеет свои собственные поля и геттеры/сеттеры.

Мне удалось отследить, что проблема не сохраняется при вызове метода:

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

Что, в свою очередь, вызывает класс:

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 для проверки)

У меня сложилось впечатление, что мне нужно иметь статическую ссылку на БД, чтобы убедиться, что я все время пытаюсь получить доступ к одной и той же БД и не смешиваю экземпляры БД.

Что я здесь делаю неправильно?


person Danny    schedule 06.01.2016    source источник
comment
глядя на ваш код, я чувствую, что HashMap будет лучше, чем ArrayList. Каждый раз не нужно повторять.   -  person Sunny    schedule 06.01.2016


Ответы (4)


Попробуйте следовать логике. Вы перебираете массив, чтобы сохранить игру. Если массив пуст, что вы ожидаете? Если бы в массиве было шесть элементов, что бы вы ожидали увидеть в этом списке? Кроме того, вы, скорее всего, столкнетесь с ConcurentModificationException, если этот цикл когда-либо будет выполняться с именем, которое уже есть в списке. Возможно, вы захотите перебрать список и сохранить дубликат в переменной. Но не делайте сохранение и удаление в цикле.

Итак, в конце концов, ваша проблема заключается в том, что вы перебираете пустой список, чтобы сохранить 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);
    }
}
person SomeJavaGuy    schedule 06.01.2016
comment
Это решило мою проблему, я полностью забыл об аспекте параллелизма. Спасибо чувак! - person Danny; 07.01.2016

Вы хотите, чтобы эти сохраненные игры были в памяти правильно. Нет проблем с тем, что они статичны. Единственная проблема заключается в том, что вы просматриваете список сохраненных игр, а также изменяете его, добавляя и удаляя несколько игр. Это не правильно. Это может дать вам исключение одновременного обновления.

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);
    }
}
person BValluri    schedule 06.01.2016

Первая проблема заключается в том, что попытка добавить игру в пустой ArrayList завершится ошибкой, потому что операция добавления выполняется в цикле, который никогда не запустится, если saveGames пуст. Также метод remove(Object obj) работает должным образом, если equals(Object obj) класса Object правильно переопределен в классе Game. Попробуйте это ниже... Переопределите метод equal() в классе игры:

@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);
}
person Kutae Shaw    schedule 06.01.2016

Ваш метод может возвращать исключение, потому что вы читаете из ArrayList и добавляете к нему содержимое в loop.

Попробуй это. :)

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