考虑一个 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).
由于 CopyOnWriteArrayList
的 iterator()
只是列表的快照,因此 Iterator
看到的某些元素可能已被删除从列表中删除它(再次)可能会导致麻烦(例如,当同一个对象多次出现在列表中时)。唯一合乎逻辑的结果是通过抛出 UnsupportedOperationException
来拒绝操作。
关于java - 迭代器、列表迭代器和 CopyOnWriteArrayList 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51088088/