Почему итератор ConcurrentSkipListMap в Java жадно кэширует следующий элемент?
Я просматривал ConcurrentSkipListMap в Java, потому что это увлекательная структура данных, и, кажется, она применима к моему использованию, но итератор обладает некоторым интересным поведением, которое мне кажется нелогичным. Возьмем для примера следующий код:
Map<String, Integer> ages = new ConcurrentSkipListMap<>();
ages.put("Bob", 28);
Iterator<Entry<String, Integer>> iterator = ages.entrySet().iterator();
System.out.println("HasBob? " + iterator.hasNext());
iterator.next();
ages.put("Jon", 25);
System.out.println("HasJon? " + iterator.hasNext());
Идея состоит в том, что карта инициализируется значениями, создает итератор и начинает итерацию. Между этими операциями другой поток помещает 'Jon' в карту. Для простоты, вместо использования реальных потоков и циклов в моем примере, я просто поместил код в надуманном порядке и напрямую ссылаюсь на каждый элемент.
Я ожидал, что результат будет true/true
, но фактический результат true/false
, Копаясь в реализации Map, я обнаружил, что итератор кэширует следующий Node/Value (в его методе advance()). Этот кеш пропускает любые последующие элементы, созданные сразу после вызова iterator.next(). Почему он жадно кэширует следующий элемент, вместо того, чтобы ждать вызова метода Iterator next() перед переходом к следующему элементу?