UnsupportedOperationException при повторении CopyOnWriteArrayList

Я наткнулся на следующее утверждение в книге:

Любые изменяющие методы, вызываемые для основанных на копировании при записи Iterator или ListIterator (например, добавление, установка или удаление), вызовут ошибку UnsupportedOperationException.

Но когда я запускаю следующий код, он работает нормально и не выдает ошибку UnsupportedOperationException.

List<Integer> list = new CopyOnWriteArrayList<>(Arrays.asList(4, 3, 52));
System.out.println("Before " + list);
for (Integer item : list) {
    System.out.println(item + " ");
    list.remove(item);
}
System.out.println("After " + list);

Приведенный выше код дает следующий результат:

Before [4, 3, 52]
4 
3 
52 
After []

Почему я не получаю исключение при изменении данного list с помощью метода remove?


person skip    schedule 23.09.2018    source источник
comment
Вы никогда не вызываете какой-либо метод для Iterator или ListIterator.   -  person JB Nizet    schedule 23.09.2018
comment
Вы вызываете remove на CopyOnWriteArrayList, а не на итератор, как упоминается в тексте, который вы цитируете. И это UnsupportedOperationException, а не UpsupportedOperationException.   -  person Jesper    schedule 23.09.2018


Ответы (2)


Вы звоните remove по самому списку, и это нормально. В документации указано, что вызов remove в итераторе списка вызовет UpsupportedOperationException. Например.:

Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
    Integer item = iter.next(); 
    System.out.println(item + " ");
    iter.remove(); // Will throw an UpsupportedOperationException
}
person Mureinik    schedule 23.09.2018

Это выглядит хорошо с ответом Мурейника. Однако, если вы углубитесь в это -

При использовании ArrayList

  • Используйте цикл for и метод списка remove(current_index), он отлично работает.

И с iterator подходом -

  • Используйте метод итератора remove() вместо списка remove(), он отлично работает
  • Выдает ConcurrentModificationException, если используется метод списка remove()

Если в многопоточной среде —

Используйте CopyOnWriteArrayList

  • Со списком remove(current_element) работает нормально
  • С методом Iterator или ListIterator remove() выдает UnsupportedOperationException

Взгляните на приведенный ниже пример -

import java.util.*;
import java.util.concurrent.*;
public class AvoidCMEExample {
   public static void main(String args[]) {
        List<String> listOfBooks = new ArrayList<>();  
       listOfBooks.add("Programming Pearls");
       listOfBooks.add("Clean Code");
       listOfBooks.add("Effective Java");
       listOfBooks.add("Code Complete");
       System.out.println("List before : " + listOfBooks);
       /*for(int i=0; i<listOfBooks.size(); i++){
           String book = listOfBooks.get(i);
           if(book.contains("Programming")){
               System.out.println("Removing " + book);
               listOfBooks.remove(i); // works fine
           }
       }*/
       Iterator<String> itr = listOfBooks.iterator();
       while(itr.hasNext()){
            String book = itr.next();
            if(book.contains("Programming")){
               System.out.println("Removing " + book);
               //listOfBooks.remove(book); // will throw CME
               itr.remove(); // using iterator remove(), it works fine
           }
       }
       System.out.println("List after : " + listOfBooks);
       
       List<String> list = new CopyOnWriteArrayList<>(); 
       list.add("B"); list.add("W"); list.add("Q"); list.add("S");
       System.out.println("\n\nList before : " + list);
       Iterator<String> itr1 = list.iterator();
       while(itr1.hasNext()){
            String book = itr1.next();
            if(book.contains("Q")){
               System.out.println("Removing " + book);
               list.remove(book); // works fine on list object remove()
               itr1.remove(); // throws UnsupportedOperationException on iterator, ListIterator obj
           }
       }
       System.out.println("List after : " + list);       
   }
}
person Ram    schedule 21.03.2021