java - 迭代器、列表迭代器和 CopyOnWriteArrayList 之间的区别

标签 java collections java.util.concurrent listiterator copyonwritearraylist

考虑一个 ArrayList,其中对于 Iterator 和 List 迭代器操作,当迭代列表时以及每当 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); } }

迭代器对象更新时情况并非如此,如下所示:

 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迭代器更新在遇到Iterator对象更改时会抛出unsupportedOperationExceptions,而当集合对象发生更改时则不会抛出异常?

3)看起来上面2个场景是相反的。请告诉我它们什么时候用在什么场景?

这完全令人困惑......

最佳答案

您的问题都由 documentation of CopyOnWriteArrayList 解答:

A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.

查看 CopyOnWriteArrayList#iterator() 的文档揭示了这一点

The returned iterator provides a snapshot of the state of the list when the iterator was constructed. No synchronization is needed while traversing the iterator. The iterator does NOT support the remove method.

重要的是,迭代器仅提供列表的快照。

Iterator#remove()要求以下行为:

Removes from the underlying collection the last element returned by this iterator (optional operation).

由于 CopyOnWriteArrayListiterator() 只是列表的快照,因此 Iterator 看到的某些元素可能已被删除从列表中删除它(再次)可能会导致麻烦(例如,当同一个对象多次出现在列表中时)。唯一合乎逻辑的结果是通过抛出 UnsupportedOperationException 来拒绝操作。

关于java - 迭代器、列表迭代器和 CopyOnWriteArrayList 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51088088/

相关文章:

java - 为什么JDK的jps命令没有列出JBoss实例的进程?

java - 游标中没有数据

java - 从 java 构建 jekyll 网站

java - 使用 Collections.sort 排序列表时出错

java - ConcurrentLinkedQueue 与 wait() 和 notify()

java - 如何在线程安全环境中定义静态Arraylist

java - Vaadin 组件样式困惑

c# - .NET 4.0 System.Collections.Concurrent 集合在 .NET 3.0 SynchronizedCollection 的功能中添加了什么?

c# - 代码契约(Contract) 1.4.40602.0 - Contract.ForAll 似乎不起作用?

java - 为 Java 7 任务编写代码的最佳方法需要先完成其他任务