Статьи

CopyOnWriteArrayList в Java

Вступление:

CopyOnWriteArrayList в Java является поточно- ориентированной реализацией интерфейса List . Он принадлежит пакету java.util.concurrent и является улучшенной версией реализации ArrayList .

Как следует из названия, CopyOnWriteArrayList создает клонированную внутреннюю копию базового ArrayList для каждой операции add () или set () . Из-за этих дополнительных накладных расходов в идеале мы должны использовать CopyOnWriteArrayList только тогда, когда у нас очень частые операции чтения, а не много вставок или обновлений.

Построение CopyOnWriteArrayList :

Мы можем использовать один из следующих конструкторов для создания CopyOnWriteArrayList :

  • CopyOnWriteArrayList (): создает пустой список
  • CopyOnWriteArrayList (Collection c): создает список, инициализированный со всеми элементами в c
  • CopyOnWriteArrayList (Object [] obj): создает список, содержащий копию данного массива obj

Давайте посмотрим на несколько примеров:

Ява

01
02
03
04
05
06
07
08
09
10
CopyOnWriteArrayList<String> emptyList
  = new CopyOnWriteArrayList<>(); //[]
  
list.add("A");
  
CopyOnWriteArrayList<String> listUsingCollection =
  new CopyOnWriteArrayList<>(list); //["A"]
  
CopyOnWriteArrayList<String> listUsingArr =
  new CopyOnWriteArrayList<>(new String[] {"A", "B"}); //["A", "B"]

Как и ArrayList , он предоставляет реализации для всех методов интерфейса List . Мы можем прочитать больше о ArrayList здесь.

Вставка и итерация над CopyOnWriteArrayList :

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

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

Однако любые изменения, внесенные позже в список, не будут видны уже созданному итератору.

Давайте попробуем это

Допустим, у нас есть экземпляр CopyOnWriteArrayList, который в настоящее время содержит два элемента:

Ява

1
2
CopyOnWriteArrayList<String> list =
  new CopyOnWriteArrayList<>(new String[] {"A", "B"});

Теперь давайте возьмем экземпляр Iterator, чтобы мы могли перебирать его элементы:

Ява

1
Iterator itr = list.iterator();

После того, как мы создали экземпляр Iterator , давайте теперь добавим еще один элемент в наш список:

Ява

1
2
     
list.add("C"); //doesn't throw an exception

Теперь давайте пройдемся по элементам нашего списка, используя itr , который мы создали ранее:

Ява

1
2
3
while(itr.hasNext()) {
    System.out.print(itr.next() + " ");
}

Код выше напечатает:

1
2
A
B

Как и ожидалось, itr не отражает текущее состояние списка и печатает только «A» и «B» в качестве его элементов. Однако, если мы создадим новый экземпляр итератора, он будет представлять точное текущее состояние списка.

Удаление и итерация над CopyOnWriteArrayList :

Итератор CopyOnWriteArrayList не поддерживает операцию удаления () . Любая попытка сделать это приведет к исключению UnsupportedOperationException:

Ява

01
02
03
04
05
06
07
08
09
10
11
@Test(expected = UnsupportedOperationException.class)
public void iterationAndRemoval() {
      
    CopyOnWriteArrayList<String> list
      = new CopyOnWriteArrayList<>(new String[]{"A", "B"});
  
    Iterator<String> itr = list.iterator();
    while (itr.hasNext()) {
        itr.remove();
    }
}

ArrayList vs CopyOnWriteArrayList:

Давайте рассмотрим различия между классами Java ArrayList и CopyOnWriteArrayList :

ArrayList CopyOnWriteArrayList
Принадлежит к пакету java.util и не является потокобезопасным Поточно-ориентированная реализация, присутствующая в пакетах java.util.concurrent.
Имеет отказоустойчивый итератор, который генерирует исключение ConcurrentModificationException при обнаружении любой модификации после начала итерации Имеет отказоустойчивый итератор, поскольку итератор содержит клонированную копию списка
Итератор поддерживает операцию удаления () Его итератор не поддерживает remove () и выдает исключение UnsupportedOperationException при любой попытке сделать это

Вывод:

В этом уроке мы узнали о поточно- ориентированной реализации Java ListCopyOnWriteArrayList . Мы также рассмотрели разницу между ArrayList и CopyOnWriteArrayList .

Оставьте первый комментарий.

Опубликовано на Java Code Geeks с разрешения Шубхры Шриваставы, партнера нашей программы JCG . Смотреть оригинальную статью здесь: CopyOnWriteArrayList В Java

Мнения, высказанные участниками Java Code Geeks, являются их собственными.