使用for(Type x:collection){...}
哪些广泛使用的集合类型可以x
在迭代期间安全地删除?
在 JavaDocs 中是否有一个技术术语需要注意?
澄清:
我最初只询问使用 for-each 语法for(Type x:collection){...}
。然而,更完整的答案将描述这种风格并使用存在差异的普通基于迭代器的循环......问题更多关于哪些标准集合允许我在迭代期间删除元素,以及如何执行迭代以允许这样做。
使用for(Type x:collection){...}
哪些广泛使用的集合类型可以x
在迭代期间安全地删除?
在 JavaDocs 中是否有一个技术术语需要注意?
澄清:
我最初只询问使用 for-each 语法for(Type x:collection){...}
。然而,更完整的答案将描述这种风格并使用存在差异的普通基于迭代器的循环......问题更多关于哪些标准集合允许我在迭代期间删除元素,以及如何执行迭代以允许这样做。
一个这样的集合是CopyOnWriteArrayList
。包中的其他集合java.util.concurrent
共享此功能。
他们的迭代器从不抛出 a 的事实是ConcurrentModificationException
此类的写时复制语义的副作用:每次修改它时,都会复制底层数组。这样做是为了允许快速并发访问经常读取但很少修改的列表。
JavaDoc 是这样解释的(强调我的):
“快照”风格的迭代器方法使用对创建迭代器时数组状态的引用。这个数组在迭代器的生命周期内永远不会改变,所以干扰是不可能的,并且迭代器保证不会抛出
ConcurrentModificationException
。
除了更新的高成本之外,这种实现还有一些进一步的缺点:
自创建迭代器以来,迭代器不会反映对列表的添加、删除或更改。不支持迭代器本身( 、 和 )
remove
上set
的元素更改操作。add
这些方法抛出UnsupportedOperationException
.
请注意,这些集合并不是用来允许“简单”循环和删除的实用程序,而是专门用于高并发情况下的集合,其中许多线程需要并发访问仍然可以更改的数据(但通常很少更改) . 不要简单地将 every 替换ArrayList
为CopyOnWriteArrayList
.
As a rule of the thumb: Anything w/ Concurrent or Blocking in its name, aka. ConcurrentLinkedList
, ConcurrentSkipListSet
, LinkedBlockingDeque
, LinkedBlockingQueue
, etc.
The keySet(), values() of ConcurrentHashMap and ConcurrentSkipListMap and so on.
Most java.util.concurrent is ConcurrentModificationException
and that is good.
COWArrayList is usually useful for either smaller sized collections or rarely modified ones... and you should avoid the explicit set
method.
One important note: using iterator.remove should be always favored to Collection.remove (except CHM.entrySet() which is impl. in a buggy way) [when availble, COWArrayList iterator does not support remove]. All non-random access structures will benefit from not having to look up the element which can be O(n).
Overall ConcurrentModificationException
was a half-baked idea and its impl. involves some side effects, incl. preventing hardware-transaction-memory to operate. It imposes extra performance costs that are rarely needed. HashMap
has a terrible impl. w/ a volatile modCount (which is written on modification and read on each itearyion, read is sorta free on x86, though).
答案可能有点晚,但是 Java 8 使得在迭代时从集合中删除元素变得更加容易:
removeIf(Predicate<? super E> filter)
删除此集合中满足给定谓词的所有元素。