Разница между итератором, итератором списка и CopyOnWriteArrayList

Рассмотрим ArrayList, где для операций Iterator и List iterator, когда список повторяется и всякий раз, когда происходит изменение в объекте Collection, он выдает ConcurrentModificationException, как показано ниже:

    package JavaImpPrograms;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

    public class Wdfds {

        public static void main(String[] args) {

            List<Integer> list=new ArrayList<>();

            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);

            Iterator it=list.iterator();

            while(it.hasNext()){

            Integer i= (Integer) it.next();

            if(i%2==0)
            list.remove(0);             
            }

            System.out.println(list); } }

Это не тот случай, когда объект Iterator обновляется, например, как показано ниже:

 while(it.hasNext()){

            Integer i= (Integer) it.next();

            if(i%2==0)
            it.remove();            
            }

        System.out.println(list); } }

И когда дело доходит до copyOnWriteArrayList , если объект итератора обновляется операцией удаления для обычного итератора, как показано ниже (или) обновляется listIterator (либо добавление/удаление), он выдает UnsupportedOperationException:

    package JavaImpPrograms;
    import java.util.Iterator;
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;

    public class Wdfds {

        public static void main(String[] args) {

            List<Integer> list=new CopyOnWriteArrayList<>();

            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);

            Iterator it=list.iterator();

            while(it.hasNext()){

            Integer i= (Integer) it.next();

            if(i%2==0)
            it.remove();            
            }

            System.out.println(list); } }

package JavaImpPrograms;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CopyOnWriteArrayList;

public class Wdfds {

    public static void main(String[] args) {

        List<Integer> list=new CopyOnWriteArrayList<>();

        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);

        ListIterator it=list.listIterator();

        while(it.hasNext()){

        Integer i= (Integer) it.next();

        if(i%2==0)
        it.add(9);          
        }

        System.out.println(list); } }

У меня есть пара вопросов с приведенными выше результатами:

1) Для ArrayList, если итератор может изменять список во время итерации с помощью объекта итератора, для чего используется copyOnWriteArrayList?

1) Почему обновления итератора copyOnWriteArrayList выдают unsupportedOperationExceptions, когда он сталкивается с изменениями объекта Iterator, но не исключение, когда есть изменение для объекта коллекции?

3) Похоже, что приведенные выше 2 сценария противоположны друг другу. Пожалуйста, дайте мне знать, когда они используются и в каких сценариях?

Это совершенно сбивает с толку...


person Pavan Ghantasala    schedule 28.06.2018    source источник
comment
Пожалуйста, отформатируйте код правильно.   -  person Turing85    schedule 28.06.2018


Ответы (2)


На все ваши вопросы ответы даны в документации CopyOnWriteArrayList :

Поточно-ориентированный вариант ArrayList, в котором все изменяющие операции (add, set и т. д.) реализуются путем создания новой копии базового массива.

Глядя на документацию CopyOnWriteArrayList#iterator() показывает, что

Возвращенный итератор предоставляет моментальный снимок состояния списка на момент создания итератора. При обходе итератора синхронизация не требуется. Итератор НЕ поддерживает метод удаления.

Важно то, что Iterator предоставляет только снимок списка.

Iterator#remove() требует следующего поведение:

Удаляет из базовой коллекции последний элемент, возвращенный этим итератором (дополнительная операция).

Поскольку iterator() элемента CopyOnWriteArrayList — это всего лишь снимок списка, некоторые элементы, видимые Iterator, уже могли быть удалены из списка, поэтому его удаление (повторное) может вызвать проблемы (например, когда один и тот же объект присутствует в списке несколько раз). . Единственным логическим последствием является отказ от операции путем выдачи UnsupportedOperationException.

person Turing85    schedule 28.06.2018

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

Чтобы преодолеть это, у нас есть CopyOnWriteArrayList, который является отказоустойчивым, мы можем добавить элемент во время обхода списка.

Понятно, что исключение параллельной модификации возникает, когда мы вызываем функцию итератора next(). Если вам интересно, как Iterator проверяет модификацию, его реализация присутствует в классе AbstractList, где определена переменная int modCount. modCount показывает, сколько раз размер списка был изменен. Значение modCount используется в каждом вызове next() для проверки любых модификаций в функции checkForComodification().

CopyOnWriteArrayList был создан, чтобы обеспечить возможность безопасного повторения элементов даже при изменении базового списка.

Из-за механизма копирования операция remove() для возвращаемого Iterator не разрешена, что приводит к исключению UnsupportedOperationException.

http://www.baeldung.com/java-copy-on-write-arraylist

person Gaurav Srivastav    schedule 28.06.2018
comment
Но почему CopyOnWriteArrayList выдает исключение для обновлений объекта Iterator? - person Pavan Ghantasala; 28.06.2018
comment
CopyOnWriteArrayList был создан, чтобы обеспечить возможность безопасного повторения элементов даже при изменении базового списка. Из-за механизма копирования операция remove() для возвращаемого Iterator не разрешена, что приводит к UnsupportedOperationException: baeldung.com/java-copy-on-write-arraylist - person Gaurav Srivastav; 28.06.2018