[英]Why CopyOnWriteArrayList's iterator allows remove() in enhanced-for loop, while its iterator does not support remove() operation?
迭代器不支持remove方法。
但為什么它在增強型for循環中有效?
List<String> lst = new CopyOnWriteArrayList<>();
lst.add("one");
lst.add("two");
lst.add("three");
for (String str : lst) {
if (str.equals("one")) {
lst.remove("two"); // no ConcurrentModificationException
}
}
System.out.println(lst); // [one, three] => removed "two" !
List<String> lst = new ArrayList<>();
會生成ConcurrentModificationException
Javadoc明確指出CopyOnWriteArrayList.iterator()
不支持remove()
=>它會拋出UnsupportedOperationException
! 我理解它是弱一致的 - 比如我從CopyOnWriteArrayList獲取迭代器之后向CopyOnWriteArrayList添加元素時沒有ConcurrentModificationException
PS 抱歉,我不專心 - 我沒有在迭代器上調用remove()! 我被置於增強型內部(它隱式使用迭代器)而感到困惑。
CopyOnWriteArrayList迭代器失敗安全實現支持修改操作。
迭代CopyOnWriteArrayList和CopyOnWriteArraySet時,迭代器使用基礎列表(或集)的快照,並且在創建快照后不反映對列表或集的任何更改。 迭代器永遠不會拋出ConcurrentModificationException。
欲了解更多信息, 請訪問: https : //markusjais.com/java-concurrency-understanding-copyonwritearraylist-and-copyonwritearrayset/
順便說一句,在像ArrayList()等經典List實現中,您不需要顯式使用迭代器。 使用list.removeIf(謂詞)方法。
如果您嘗試使用iterator
從CopyOnWriteArrayList
刪除元素。 它會引發異常。 這就是javadoc試圖說的。
碼:
List<String> lst2 = new CopyOnWriteArrayList<String>();
lst2.add("one");
lst2.add("two");
lst2.add("three");
Iterator<String> iterator2 = lst2.iterator();
while (iterator2.hasNext()) {
if (iterator2.next().equals("two")) {
iterator2.remove();
}
}
System.out.println(lst2.toString());
輸出:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1178)
at MyClass.main(MyClass.java:29)
但是如果你在Arraylist
上做同樣的事情。 它會工作正常。
來源: ArrayList
碼:
List<String> lst = new ArrayList<String>();
lst.add("one");
lst.add("two");
lst.add("three");
Iterator<String> iterator = lst.iterator();
while (iterator.hasNext()) {
if (iterator.next().equals("two")) {
iterator.remove();
}
}
System.out.println(lst.toString());
輸出:
[one, three]
雖然如果你不想使用迭代器,你可以使用public boolean removeIf(Predicate<? super E> filter)
,它只是一行,並提供與上面相同的輸出。
lst.removeIf(n -> (n.equals("two")));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.