遍历CopyOnWriteArrayList时出现UnsupportedOperationException

时间:2018-09-23 15:37:20

标签: java collections concurrency iterator copyonwritearraylist

我在一本书中遇到以下陈述:

  

在基于写时复制的IteratorListIterator上调用的任何变异方法(例如添加,设置或删除)都将抛出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时没有得到异常?

2 个答案:

答案 0 :(得分:6)

您正在列表本身上呼叫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
}

答案 1 :(得分:0)

Mureinik 的回答看起来不错。但是,如果你深入研究这个 -

如果使用 ArrayList

  • 使用 for 循环和列表 remove(current_index) 方法,效果很好。

并使用 iterator 方法 -

  • 使用迭代器 remove() 方法代替列表 remove(),效果很好
  • 如果使用列表 ConcurrentModificationException 方法,则抛出 remove()

如果在多线程环境中 -

使用CopyOnWriteArrayList

  • 使用列表 remove(current_element) 可以正常工作
  • 使用 IteratorListIterator 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);       
   }
}