Java: `iterator.remove` создает исключение IllegalStateException - PullRequest
0 голосов
/ 01 февраля 2020

У меня iterator внутри thread, и я пытаюсь удалить дубликаты записей.

 Runnable readingThread = new Runnable() {
        @Override
        public void run() {

            Iterator<Demand> iterator = null;
            for (iterator = demandListFromFile.iterator(); iterator.hasNext();) {
                Demand demand = iterator.next();

                /**
                 * Find and assign the Item ID
                 */
                if (itemListHashMap.containsValue(demand.getItem().getItemName())) {
                    demand.getItem().setIditem(itemListHashMapReversed.get(demand.getItem().getItemName()));

                } else {
                    unavailableItemsList.add(demand.getItem().getItemName());
                }


                /**
                 * Find and remove duplicate records
                 */
                for (Map.Entry<Date, String> entry : demandListHashMap.entries()) {

                    if (demand.getDueDate().equals(entry.getKey()) && demand.getItem().getItemName().equals(entry.getValue())) {

                        iterator.remove();
                    }

                }

            }

        }

После удаления нескольких элементов iterator.remove выдает следующее исключение

Exception in thread "Thread-0" java.lang.IllegalStateException
    at java.base/java.util.ArrayList$Itr.remove(ArrayList.java:1009)
    at com.xxx.xxx.ui.Home$7.run(Home.java:455)
    at java.base/java.lang.Thread.run(Thread.java:834)

Почему это происходит? Обратите внимание, что я удалил код после и перед итератором, чтобы этот пост был коротким.

Ответы [ 2 ]

3 голосов
/ 01 февраля 2020

Итератор. java метод удаления:

    @throws IllegalStateException if the next method has not
              yet been called, or the remove method has already
              been called after the last call to the next method
    void remove() {
        ..
    }

Проблема в том, что для вас l oop «Найти и удалить дубликаты записей» вы можете вызывать iterator.remove более одного раза. Метод remove удаляет текущий просматриваемый элемент, поэтому вы можете вызывать его только один раз, используя next (). Чтобы разрешить вызов только один раз, добавьте оператор break ниже iterator.remove();

0 голосов
/ 01 февраля 2020

Причина, указанная @ CausingUnderflowsEverywhere , была абсолютно верной.

Кроме того, после просмотра реализации элемент iterator.remove вызывает метод ArrayList.remove внутри.

ArrayList поддерживает индекс последнего элемента, возвращенного в переменной с именем lastRet. После удаления элемента метод ArrayList.remove устанавливает lastRet в -1.

И самая первая проверка ArrayList.remove -

if (lastRet < 0)
{
     throw new IllegalStateException();
}

Это то, что происходит в фоновом режиме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...