Безопасно ли добавлять элементы в 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, а не на лёгкое утверждение " да" или " нет". Я также знаю, что SortedSet может быть сделано неизменяемым, что сделало бы SortedSet.add() потерпеть поражение; Я заинтересован в случае изменяемого SortedSet,

Обратите внимание, что я спрашиваю о добавлении элементов в набор, а не об изменении элементов в наборе.

2 ответа

Решение

Если поведение не указано, реализация может свободно выбирать поведение.

Например, два класса, перечисленные как известные классы реализации в Javadoc, реализуют оба поведения:

  • ConcurrentSkipListSet:

    Итераторы слабо согласованы, возвращая элементы, отражающие состояние множества в некоторой точке во время или после создания итератора. Они не генерируют исключение ConcurrentModificationException и могут выполняться одновременно с другими операциями.

  • TreeSet:

    Итераторы, возвращаемые методом итератора этого класса, не подвержены сбоям: если набор изменяется в любое время после создания итератора, любым способом, кроме как через собственный метод удаления итератора, итератор генерирует исключение ConcurrentModificationException.

Тем не менее, более фундаментально, Collection.add (а также Set.add) задокументирована как необязательная операция, поэтому мы никогда не можем полагаться на вызов SortedSet.add быть в безопасности, независимо от того, происходит ли в контексте продолжающаяся итерация или нет.

Например, позвонив add на SortedSet вернулся Collections.unmodifiableSortedSet или гуава ImmutableSortedSet приведет к UnsupportedOperationException,

Это зависит от реализации. Например, в случае TreeSet, итераторы отказоустойчивы, поэтому добавление элементов во время итерации вызовет ConcurrentModificationException,

Из JavaDoc TreeSet:

Итераторы, возвращаемые методом итератора этого класса, не подвержены сбоям: если набор изменяется в любое время после создания итератора, любым способом, кроме как через собственный метод удаления итератора, итератор генерирует исключение ConcurrentModificationException. Таким образом, перед одновременной модификацией итератор быстро и чисто дает сбой, вместо того, чтобы рисковать произвольным недетерминированным поведением в неопределенное время в будущем.

В других реализациях с итераторами, не подверженными сбоям, можно добавлять элементы во время итерации.

Другие вопросы по тегам