2016-11-28 3 views
-2

Я создаю онлайн-видеоигра с использованием Java. Если у вас есть клиент и серверное приложение. На сервере для обработки базы данных проигрывателя я создаю ArrayList с именем inGamePlayers, который содержит объект Players (с именем InetAdress ipAdress и именем пользователя String).Java ConcurrentModificationException с ArrayList

Когда игрок подключается, сначала проверьте, является ли имя пользователя соединительного игрока == одному из игроков в имени пользователя ArrayList. Если нет, он добавляет его в список. Кроме того, соединительный проигрыватель считается «повторно подключенным» ...

Когда он работает на 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; 
    } 
} 
+2

Можете ли вы опубликовать весь 'for' цикл. Очевидно, что ошибка исходит не только из этой строки. – Mat

+0

Итерация по регулярным коллекциям взрывается с помощью 'ConcurrentModificationException', если вы изменяете коллекцию во время итерации. Простое исправление: используйте 'Set' (например,' HashSet') и не проверяйте, просто добавьте - набор обеспечит отсутствие дубликатов. Эта «проницательность» доступна в javadoc. – Bohemian

+0

@ ΦXocę 웃 Пepeúpa ツ OP даже не требуется несколько потоков - AFAICT он добавляет внутри цикла – Bohemian

ответ

3

Этот код имеет несколько недостатков. В этой форме он будет добавлять новые экземпляры проигрывателя до тех пор, пока не будет найдена запись с совпадающим именем. Запуск итерации, изменение списка и продолжение итерации вызовут 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); 
    } 
} 
+0

Благодарим вас за альтернативное решение! @PravinSonawane прав, я не могу изменить свой ArrayList, итерации по нему – GriffinBabe