Отказоустойчивый итератор
Я получаю это определение: как следует из названия, быстрые итераторы терпят неудачу, как только они поняли, что структура Collection была изменена с начала итерации.
что это значит с начала итерации? это означает, что после Iterator это =set.iterator() эта строка кода?
public static void customize(BufferedReader br) throws IOException{
Set<String> set=new HashSet<String>(); // Actual type parameter added
**Iterator it=set.iterator();**
5 ответов
Прежде всего, они отказоустойчивы, не отказоустойчивы.
Контракт заключается в том, что структурные модификации (т.е. вставки / удаления) определенных типов коллекций делают недействительными существующие итераторы в коллекции. Отказоустойчивые итераторы пытаются обнаружить, что они не должны быть действительными, и выбрасывают ConcurrentModificationException
, Это делается для вас, программиста, как услуга, помогающая быстрее обнаруживать ошибки этого типа.
В вашем примере:
Iterator it = set.iterator();
it.next();
set.add("unique-entry"); // invalidates the iterator
it.next();
Если вам повезет, второй it.next()
обнаружит недопустимое использование и выдаст исключение. Обратите внимание, что это делается на основе максимальных усилий и не гарантируется.
это означает, что после Iterator это =set.iterator() эта строка кода?
Да. Если вы посмотрите на код для HashSet.iterator()
вы увидите, что это просто так:
return map.keySet().iterator();
... какой делегат HashMap.KeySet.iterator()
, В цепочке есть еще несколько ссылок, но в итоге вы получите HashMap.HashIterator
, который содержит это в конструкторе:
private abstract class HashIterator<E> implements Iterator<E> {
int expectedModCount; // For fast-fail
...
HashIterator() {
expectedModCount = modCount;
...
}
}
... где modCount
это поле во включающем экземпляре HashMap
который отслеживает количество модификаций.
Быстро сбой итератора означает, что следующий фрагмент кода, как ожидают, потерпит неудачу:
Set<String> set = new HashSet<String>();
Iterator<String> it = set.iterator();
set.add("");
it.next(); // the set has changed now, and the iterator will throw an exception
потому что происходит следующая серия событий: создается итератор, затем изменяется его базовая коллекция, затем осуществляется доступ к итератору.
Да, не изменяйте коллекцию после использования.iterator(), если вы планируете выполнять итерации по ней, вы можете использовать.remove(), если вы хотите удалить последний элемент, хотя
Перед тем как Fail Fast Iterator начинает работать, он получает счетчик сбора и после любой итерации проверяет, изменился ли счетчик или нет, а в случае изменения счетчика JVM сгенерирует исключение ConcurrentModificationException. Отказоустойчивые итераторы - это любые итераторы коллекции, которые находятся внутри пакета java.util (например, ArrayList, LinkedList и т. Д.), А итераторы Fail Safe - это итераторы, которые находятся внутри пакета java.concurrent (например, CopyOnWriteArrayList, CopyOnWriteSet и т. Д.). Итераторы Fail Fast выдают исключение в случае одновременной модификации, но итератор Fail Safe в основном работает с копией коллекции, которая не выдает исключение в случае одновременной модификации.