Java ConcurrentModificationException при удалении двух индексов, текущего и случайного

1

У меня есть список игроков. Этот список содержит игроков, у которых нет целей. Цели означают, что игрок нацелен на другого игрока, они два являются объектами и не должны быть в списке.

Целью следующего цикла является циклическое перемещение всех игроков и поиск цели, и если игрок еще не готов, он просто вызовет метод 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 который содержит текущий индекс и найденные объекты целевого индекса.

Если возвращаемый экземпляр SharedTargetDomain из search(Client) не был пустым, я удалю оба объекта из списка participants используя removeAll()

К сожалению, если я удалю любой из них, я получу следующую ошибку:

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) {

Почему я получаю это? Я пробовал использовать 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 ? Iterator прекрасно работает, чтобы удалить элемент во время итерации.
  • 0
    Проблема не в текущем индексе, исключения ConcurrentModificationExceptions возникают, когда вы изменяете список, который использует что-то еще. Можете ли вы показать нам реализацию, которую вы использовали с итераторами?
Показать ещё 3 комментария
Теги:
arrays
loops
exception

2 ответа

3
Лучший ответ

Проблема в том, что вы изменяете коллекцию во время ее итерации.

Есть как минимум два решения

  1. Используйте доступ к индексу. Вы получаете массу удовольствия от индексов обработки, потому что после удаления элемент будет смещен.
  2. Соберите элементы, которые вам нужно удалить и применить все изменения после окончания итерации. Вы получаете много удовольствия, всегда имея в виду, что элемент, который вы можете обработать, может быть уже запланирован для удаления.
  • 0
    пойти со вторым вариантом.
  • 1
    Вы также можете использовать CopyOnWriteArrayList
Показать ещё 5 комментариев
0

Вы можете использовать

CopyOnWriteArrayList, чтобы избежать этого исключения

Ещё вопросы

Сообщество Overcoder
Наверх
Меню