Разница между Итератором, Итератором Списка и CopyOnWriteArrayList - PullRequest
0 голосов
/ 28 июня 2018

Рассмотрим ArrayList, где для операций итератора и итератора списка, когда список повторяется и когда происходит изменение в объекте 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 сценария противоположны друг другу. Пожалуйста, дайте мне знать, когда они используются и в каких сценариях?

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

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

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

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

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

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

Из-за механизма копирования операция remove () на возвращенный итератор недопустим - в результате UnsupportedOperationException.

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

0 голосов
/ 28 июня 2018

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

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

Просмотр документации CopyOnWriteArrayList#iterator() показывает, что

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

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

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

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

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

...