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

Is it safe to add elements to a SortedSet while iterating

在迭代该集合时向可修改的 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 的文档中缺少明确的声明不足以 以一种或另一种方式回答问题;所需的行为可能在不同 class 或接口的文档中间接指定。遗憾的是,JRE 文档编写者并不总是明确说明允许的内容。因此,我正在寻找引用 JRE API 的答案,而不是 yesno 的空头断言。我也知道 SortedSet 可以变成 unmodifiable,这会使 SortedSet.add() 失败;我对可修改 SortedSet.

的情况感兴趣

请注意,我问的是向集合中添加元素,而不是 modifying elements within the set

这取决于实施。例如在 TreeSet 的情况下,迭代器是 fail-fast,因此在迭代时添加元素将触发 ConcurrentModificationException.

来自 TreeSet 的 JavaDoc:

The iterators returned by this class's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

具有非快速失败迭代器的其他实现可能允许在迭代时添加元素。

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

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

  • ConcurrentSkipListSet:

    Iterators are weakly consistent, returning elements reflecting the state of the set at some point at or since the creation of the iterator. They do not throw ConcurrentModificationException, and may proceed concurrently with other operations.

  • TreeSet:

    The iterators returned by this class's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException.

然而,更根本的是,Collection.add (and Set.add) 被记录为可选操作,因此我们 永远不会 依赖对 SortedSet.add 的调用是安全的,是否在上下文中进行迭代。

例如,在 Collections.unmodifiableSortedSet or a Guava ImmutableSortedSet 返回的 SortedSet 上调用 add 将导致 UnsupportedOperationException.