使用ListIterator时,我们什么时候(或什么时候不)允许并发修改?

时间:2019-03-31 03:15:51

标签: java concurrentmodification 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)
}

是否应该有一些实现会从ConcurrentModificationException中抛出ListIterator#set?或者,是否存在应该引起异常抛出的 specific 修改类型(即“结构”)?是否暗示List的某些实现可以合理地引发上述操作的异常?

1 个答案:

答案 0 :(得分:5)

  

是否应该有一些实现会从ConcurrentModificationException中抛出ListIterator::set

答案是可能存在

ListListIteratorConcurrentModificationException的Javadocs会不加修饰地说明允许不允许的修改条款详细介绍允许的内容。如果查看(例如)ArrayList的javadocs,您会发现它表明在迭代过程中允许不引起结构修改的更改。但是,这并不适用于所有列表类型。例如在CopyOnWriteArrayList的迭代过程中允许进行所有修改。

自定义列表类型可以对修改施加不同的约束。

  

或者,是否存在应该引起异常抛出的特定类型的修改(即“结构化”)?

ListIterator::set不是结构修改。但是对于某些列表类,在迭代过程中进行“结构”修改将导致CME。

其他(假设的)示例:

  • 可以实现一个自定义列表类 ,如果(例如)两个迭代器处于活动状态,则不允许set操作,如果发生则抛出CME。

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

这些可能可能是不同的例外;例如UnsupportedOperationException。我对javadocs的理解是CME 是合适的。

  

是否暗示List的某些实现可能合理地引发上述操作的异常?

是的。自定义List实现只要符合ListCollection API中定义的行为,就可以完成各种“有趣”的事情。


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

A:IMO编写您的代码是合理的,这样它就可以用于“正常”列表。不可能允许自定义列表类可能做的所有疯狂的事情。