[英]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
线程安全变体,其中所有可变操作(add
,set
等)都是通过对基础数组进行全新复制来实现的。
查看CopyOnWriteArrayList#iterator()
的文档可以发现,
返回的迭代器在构造迭代器时提供列表状态的快照。 遍历迭代器时不需要同步。 迭代器不支持remove方法。
重要的是Iterator
仅提供列表的快照。
Iterator#remove()
要求以下行为:
从基础集合中移除此迭代器返回的最后一个元素(可选操作)。
由于CopyOnWriteArrayList
的iterator()
只是列表的快照,因此Iterator
看到的某些元素可能已经从列表中删除,因此(再次)删除它可能会造成麻烦(例如,当同一对象位于列表中多个次)。 唯一的逻辑结果是,抛出UnsupportedOperationException
来拒绝该操作。
迭代器有两种类型:“故障安全”和“快速故障”。 Iterator快速失败,这意味着当您遍历集合并尝试通过添加新元素来修改集合的结构时,会引发ConcurrentModificationException 。
为了克服这个问题,我们有一个CopyOnWriteArrayList是安全的,我们可以在遍历列表时添加元素。
很明显,当我们调用迭代器next()函数时,并发修改异常即将到来。 如果您想知道Iterator如何检查修改,则其实现在定义了int变量modCount的AbstractList类中提供。 modCount提供更改列表大小的次数。 在每个next()调用中都使用modCount值来检查功能checkForComodification()中是否有任何修改。
创建CopyOnWriteArrayList的目的是,即使对基础列表进行了修改,也可以对元素进行安全的迭代。
由于存在复制机制,因此不允许对返回的Iterator进行remove()操作-导致UnsupportedOperationException。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.