在迭代时向SortedSet添加元素是否安全

时间:2016-03-02 16:00:10

标签: java sortedset

在迭代该集合时,将元素添加到可修改的SortedSet是否安全?特别是,将元素添加到集合中的元素是否比迭代器指示的元素更安全?

例如,以下代码是否会损坏SortedSet s或抛出异常(可能是ConcurrentModificationException):

 /**
  * s not null, is modifiable.
  */
 private final addSelectedFollowers(final SortedSet<Integer> s)
 {
    for (Integer i: s) {
       if (shouldAddNext(i)) {
          s.add(i + 1);
       }
    }
 }

 protected abstract boolean shouldAddNext(int i);

我的猜测是 安全,但我在JRE API文档中找不到明确的声明。我知道如果没有指定行为,实现可以自由决定行为。在SortedSet 的文档中缺乏明确的陈述是不够的以这种或那种方式回答问题;可以在不同类或接口的文档中间接指定所需行为。遗憾的是,JRE记录员并不总是明确说明允许的内容。因此,我正在寻找引用JRE API的答案,而不是 no 的光头断言。我也知道可以SortedSet SortedSet.add(),这会使SortedSet失败;我对可修改a(k,l)

的情况感兴趣

请注意,我要求在集合中添加元素,而不是unmodifiable

2 个答案:

答案 0 :(得分:6)

这取决于实施。例如,在TreeSet的情况下,迭代器是故障快速,因此在迭代时添加元素将触发ConcurrentModificationException

来自TreeSet的JavaDoc:

  

此类的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时间修改集合,除了通过迭代器自己的删除方法之外,迭代器将抛出ConcurrentModificationException。因此,面对并发修改,迭代器会快速而干净地失败,而不是在未来不确定的时间冒着任意的,非确定性行为的风险。

使用非故障快速迭代器的其他实现可能允许在迭代时添加元素。

答案 1 :(得分:5)

如果未指定行为,则实现可以自由决定行为。

例如,Javadoc中列为已知实现类的两个类实现了两种行为:

  • ConcurrentSkipListSet

      

    迭代器是弱一致的,在迭代器创建时或之后的某个时刻返回反映集合状态的元素。 它们不会抛出ConcurrentModificationException ,并且可能会与其他操作同时进行。

  • TreeSet

      

    此类的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时间修改了set,​​除了通过迭代器自己的remove方法之外,迭代器将抛出ConcurrentModificationException

但是,更基本的是,Collection.add(和Set.add)被记录为可选操作,因此我们永远不会依赖对SortedSet.add的调用无论是否在正在进行的迭代中,都是安全的。

例如,在Collections.unmodifiableSortedSetGuava ImmutableSortedSet返回的add上调用SortedSet会产生UnsupportedOperationException