Когда мы (или когда нет) разрешаем одновременное изменение при использовании ListIterator? - PullRequest
4 голосов
/ 31 марта 2019

Например, скажем, есть какая-то операция 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? Или, скорее, существует определенный тип модификации (то есть "структурный"), который должен вызывать выброс исключения? Подразумевается ли, что некоторые реализации List могут оправданно вызвать исключение из вышеупомянутой операции?

1 Ответ

5 голосов
/ 31 марта 2019

Должна ли когда-нибудь существовать реализация, которая выбрасывает ConcurrentModificationException из ListIterator::set?

Ответ таков: может быть.

Javadocs для List, ListIterator и ConcurrentModificationException говорят о терминах модификаций, которые допустимы и недопустимы , не вдаваясь в подробности того, чтодопустимоЕсли вы посмотрите на javadoc для (скажем) ArrayList, вы увидите, что в нем говорится, что изменения, которые не вызывают структурных изменений, допустимы во время итерации.Однако это относится не ко всем типам списков;например, все модификации разрешены во время итерации для CopyOnWriteArrayList.

Пользовательский тип списка может накладывать различные ограничения на модификации.

Или, скорее, существует определенный тип модификации (то есть "структурная"), который долженвызвать исключение?

Ну ListIterator::set не является структурной модификацией.Но для некоторых классов списков «структурная» модификация во время итерации приведет к CME.

Другие (гипотетические) примеры:

  • Пользовательский класс списка можетРеализовано , которое не разрешало бы операции set, если (скажем) были активны два итератора, и выбрасывало CME, если это произошло.

  • В пользовательском списке, который представлял собой отсортированное представление чего-то другого, вызов set, который нарушил порядок, может вызвать CME.

Можно утверждать, что может быть другим исключением;например, UnsupportedOperationException.Мое чтение javadocs - то, что CME будет подходящим.

Подразумевается ли, что некоторые реализации List могут оправданно вызвать исключение из вышеупомянутой операции?

Да.Пользовательская реализация List может делать все виды «интересных» вещей, если она соответствует поведению, определенному в API List и Collection.


Q: Вам нужноРазрешить это в вашем коде?

A: IMO разумно написать ваш код, чтобы он работал для "обычных" списков.Невозможно учесть все сумасшедшие вещи, которые может делать пользовательский класс списка.

...