繁体   English   中英

Iterator,List迭代器和CopyOnWriteArrayList之间的区别

[英]Difference between Iterator,List iterator and 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); } }

更新Iterator对象时情况并非如此,即如下所示:

 while(it.hasNext()){

            Integer i= (Integer) it.next();

            if(i%2==0)
            it.remove();            
            }

        System.out.println(list); } }

当涉及到copyOnWriteArrayList时,如果使用普通迭代器的remove操作更新迭代器对象,如下所示(或)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)以上两种情况看起来是相反的,请让我知道它们何时使用以及在哪些情况下使用?

完全令人困惑...

CopyOnWriteArrayList文档都回答了您的问题:

ArrayList线程安全变体,其中所有可变操作( addset等)都是通过对基础数组进行全新复制来实现的。

查看CopyOnWriteArrayList#iterator()的文档可以发现,

返回的迭代器在构造迭代器时提供列表状态的快照。 遍历迭代器时不需要同步。 迭代器不支持remove方法。

重要的是Iterator仅提供列表的快照。

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

从基础集合中移除此迭代器返回的最后一个元素(可选操作)。

由于CopyOnWriteArrayListiterator()只是列表的快照,因此Iterator看到的某些元素可能已经从列表中删除,因此(再次)删除它可能会造成麻烦(例如,当同一对象位于列表中多个次)。 唯一的逻辑结果是,抛出UnsupportedOperationException来拒绝该操作。

迭代器有两种类型:“故障安全”和“快速故障”。 Iterator快速失败,这意味着当您遍历集合并尝试通过添加新元素来修改集合的结构时,会引发ConcurrentModificationException

为了克服这个问题,我们有一个CopyOnWriteArrayList是安全的,我们可以在遍历列表时添加元素。

很明显,当我们调用迭代器next()函数时,并发修改异常即将到来。 如果您想知道Iterator如何检查修改,则其实现在定义了int变量modCount的AbstractList类中提供。 modCount提供更改列表大小的次数。 在每个next()调用中都使用modCount值来检查功能checkForComodification()中是否有任何修改。

创建CopyOnWriteArrayList的目的是,即使对基础列表进行了修改,也可以对元素进行安全的迭代。

由于存在复制机制,因此不允许对返回的Iterator进行remove()操作-导致UnsupportedOperationException。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM