在使用 ListIterator 时,我们何时(或何时不允许)允许并发修改?

When do we (or when do we not) allow concurrent modification when using ListIterator?

例如,假设有一些 Collections#reverse(List) 操作这样使用 ListIterator

var forwardItr = list.listIterator();
var reverseItr = list.listIterator(list.size());
while (forwardItr.nextIndex() < reverseItr.previousIndex()) {
  var forward = forwardItr.next();
  var reverse = reverseItr.previous();
  forwardItr.set(reverse)
  reverseItr.set(forward)
}

是否应该有一些实现从 ListIterator#set 中抛出 ConcurrentModificationException?或者更确切地说,是否存在应该导致异常抛出的 特定 类型的修改(即 "structural")?是否暗示 List 的某些实现可能会合理地从上述操作中抛出异常?

Should there ever be some implementation that throws a ConcurrentModificationException from ListIterator::set?

答案是可能

ListListIteratorConcurrentModificationException 的 javadoc 讨论了 允许 不允许的修改条款permissible 而不是详细说明什么是允许的。如果您查看(比如)ArrayList 的 javadoc,您会看到它表示在迭代期间允许不导致结构修改的更改。但是,这并不适用于所有列表类型;例如在 CopyOnWriteArrayList 的迭代期间允许所有修改。

自定义列表类型可以对修改设置不同约束。

Or rather, is there a particular type of modification (i.e. "structural") that should cause an exception throw?

ListIterator::set不是结构修改。但是对于某些列表 classes,迭代期间的 "structural" 修改将导致 CME。

其他(假设的)示例:

  • 自定义列表 class 可以 实现,如果(比如)两个迭代器处于活动状态,则不允许 set 操作,如果发生这种情况,请抛出 CME。

  • 在作为其他内容的排序视图的自定义列表中,破坏排序的 set 调用可能会引发 CME。

有争议,这些可能是不同的例外;例如UnsupportedOperationException。我对 javadoc 的阅读是 CME 是合适的。

Is it implied that some implementations of List may justifiably throw an exception from the aforementioned operation?

是的。自定义 List 实现可以做各种 "interesting" 事情,只要它符合 ListCollection API 中定义的行为。


问:您需要在代码中允许这样做吗?

答:IMO 编写您的代码使其适用于 "normal" 列表是合理的。不可能允许自定义列表 class 可能做的所有疯狂事情。