Получение ConcurrentException при обходе списка - PullRequest
4 голосов
/ 13 апреля 2011

Я нахожусь в очень странном состоянии. У меня есть список что-то вроде ниже: -

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");

Теперь, когда я делаю обход нескольких типов, например, использую расширенный для, итератор и нормальный для цикла, ниже приведены примеры фрагментов кода: -

1> Расширенный цикл: -

try {
    for(String a : list) {
        System.out.println(a);
        list.add("f");
    }
} catch (Exception e) {
    e.printStackTrace();
}

2> Итератор: -

try {
    Iterator<String> itr =  list.iterator();
    while(itr.hasNext()) {
        System.out.println(itr.next());
        list.add("f");
    }
} catch (Exception e) {
    e.printStackTrace();
}

3> Нормальный цикл: -

for (int i=0;i<list.size();i++) {
    System.out.println(list.get(i));
    list.add("f");
}

Теперь особая проблема заключается в том, что при использовании расширенного цикла for и итератора я получаю следующее исключение: -

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)


the reason i know, that while iterating through a list, one cannot modify it parallely.

но когда я использую цикл for, то он работает правильно, я что-то упустил ??

Пожалуйста, помогите !!! ..

Ответы [ 4 ]

7 голосов
/ 13 апреля 2011

Если вы изменяете список, он делает недействительными любые объекты итераторов, созданные из него.Расширенный цикл (1) компилируется почти в тот же код, что и цикл итератора (2), что означает, что за кулисами создается объект Итератор.

Javadocs для ConcurrentMOdificationException имеют большедетали.

Если вы хотите добавить во время итерации, используйте

ListIterator listIter = ...
while(listIter.hasNext())
{
    if(shouldAdd(iter.next())) {
        iter.add(....)
    }
}
3 голосов
/ 13 апреля 2011

Расширенный цикл - просто синтаксический сахар для итератора. Итератор всегда вызывает checkForComodification() всякий раз, когда он запускает next(). Этот метод вызовет исключение, если увидит, что вы изменили список.

Запуск «Обычного цикла» не обеспечивает эту функцию проверки количества модификаций, потому что вы не используете итератор для цикла, вы строго используете конструкцию цикла for.

0 голосов
/ 13 апреля 2011

Следует помнить, что исключение ConcurrentModificationException вызывается следующим методом Итератора, но не методом добавления Списка. Это означает, что список фактически изменяется, когда вы добавляете новый элемент в цикл. Если вы выходите из цикла после добавления нового элемента, исключение не выдается, и элемент добавляется в список.

В противном случае вы можете использовать метод итератора add и remove для изменения списка внутри цикла.

0 голосов
/ 13 апреля 2011

Выполнение цикла for в списке создаст серьезные проблемы.Вы получите перечитываемые записи (это может привести к удалению предыдущей записи), и вы можете получить IndexOutOfBoundsExceptions.Используйте CopyOnWriteArrayList для одновременного безопасного списка с небольшими накладными расходами, в зависимости от вашего приложения.Если у вас много записей в списке, используйте ConcurrentLinkedQueue , но имейте в виду, что это действует как очередь, и вы можете делать с ней только такие вещи, как очередь, только добавление в конец и удаление с фронта.

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