Перебор коллекций для добавления элементов, но выбрасывает ConcurrentModificationException

#java #arraylist #collections #concurrentmodification

Вопрос:

 package com.ripal;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Iterator;

public class Outputs {

    public void show() {
        final ArrayList<String> list = new ArrayList<String>();

        list.add("banana");
        list.add("apple");

        Iterator<String> itr = list.iterator();

        Collections.sort(list);
        while (itr.hasNext()) {
            System.out.println(itr.next()   " ");
        }
    }
}

class Test {

    public static void main(String[] args) {
        Outputs outputs = new Outputs();
        outputs.show();
    }
}
 

Ответ №1:

ArrayList имеет быстрый итератор сбоев. Вы можете изменять коллекцию только с помощью итератора. Любая другая модификация, выполненная снаружи, обнаруживается раньше после вызова методов итератора и ConcurrentModificationException генерируется a . В вашем случае после создания итератора вы сортируете массив на месте, и эта процедура сортировки изменяет содержимое массива, ConcurrentModificationException что приводит к использованию итератора. Чтобы устранить проблему, просто выполните сортировку перед созданием итератора. Вот как это выглядит.

 Collections.sort(list);
Iterator<String> itr = list.iterator();
 

Комментарии:

1. Альтернатива состоит в том, чтобы не иметь дело с итераторами, когда в этом нет необходимости: for(String s: list) System.out.println(s); (Пустое пространство в конце строки в любом случае бессмысленно, альтернативой было System.out.println(String.join(" ", list)); бы, если бы это было фактическое намерение).

2. Что интересно в этом, так это то, что в документации ArrayList говорится, что CME генерируется, если вы структурно изменяете список; но сортировка ArrayList не является структурной модификацией (это просто перемещение элементов в массиве) (например, вы можете отсортировать список, который нельзя структурно изменить, Arrays.asList ). Но исходный код явно обновляет modCount .

3. Похоже replaceAll , аналогично обновляет modCount без структурных изменений.