Будет ли исключение одновременной модификации при использовании классического цикла for?

Есть ли вероятность получения исключения параллельной модификации при использовании классического цикла for?

import java.util.*;

class IterTest{
    public static void main(String[] args){
        List<Integer> nums = new ArrayList<>();
        nums.add(18);
        nums.add(1);
        nums.add(14);
        nums.add(13);
        System.out.println("Nums ->"+nums);
        int len = nums.size();
        for(int index=0;index < len ;index++){          
            System.out.println(" Current >>"+nums.get(index));
            System.out.println(" Removing >>"+nums.remove(index));          
        }
    }
}

2 ответа

Нет, шансов нет. Исключение одновременного изменения может возникнуть при использовании итераторов, см. Что такое отказоустойчивые и отказоустойчивые итераторы в Java

Нет, этот код не даст ConcurrentModificationException, Это исключение обычно возникает, когда представление коллекции "испорчено" из-за того, что коллекция из-под нее исключена. Типичные примеры этого - изменение коллекции, пока она повторяется Iterator (который неявно используется в расширенном операторе for) или получая subList(), изменяя базовый список, а затем продолжая использовать подсписок.

Однако этот код будет работать в том же состоянии, которое "портит" цикл, за исключением того, что будет выдано другое исключение. Границы цикла основаны на начальном размере списка. Однако тело цикла удаляет элементы из списка, поэтому код в конечном итоге будет индексироваться за пределами списка, в результате чего IndexOutOfBoundsException,

Как исправить этот код, зависит от того, что вы пытаетесь сделать. Сначала может показаться разумным, чтобы избежать ConcurrentModificationException используя списочные индексы вместо Iterator, Однако, если список структурно изменен (то есть элементы добавлены или удалены) во время цикла, необходимо тщательно отрегулировать границы индекса и цикла, в противном случае элементы могут быть пропущены, дублированы или IndexOutOfBoundsException может возникнуть.

Нет, как предлагали другие ответы, ConcurrentModificationException не будет происходить в данном коде.

Так когда же происходит ConcurrentModificationException?

В однопоточной среде это обычно происходит, когда вы используете итераторы, чтобы перебрать коллекцию и изменить ее одновременно.

Зачем?

Если вы проверяете исходный код реализаций Iterator, он всегда выполняет checkForComodification() всякий раз, когда вы используете какой-либо метод итератора (например, next(), remove()). Код для этого метода в ArrayList.java, например:

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

Где modCount - статическая переменная, поддерживаемая на уровне класса ArrayList, которая указывает, сколько раз этот список был структурно изменен. Ожидаемый счетчик ожидаемых модификаций Ожидаемый ModCount поддерживается на уровне класса Iterator, который изначально равен modCount.

Таким образом, всякий раз, когда ожидаемое количество модификаций не соответствует фактически выполненным модификациям, вы получаете исключение.

Так как в вашем случае вы не использовали ничего из этого, не будет проверки на совместную модификацию, и, следовательно, вы не получите ConcurrentModificationException,

Примечание: как указано в этом ответе, вы получите IndexOutOfBoundsException так как вы проверили index < len в вашем для цикла и len инициализируется до начального размера массива. Простое решение этого было бы:

 for(int index=0;index < nums.size;index++)
Другие вопросы по тегам