我正在查看 Java 的 ConcurrentSkipListMap,因为它是一个引人入胜的数据结构并且似乎适用于我的使用,但迭代器有一些有趣的行为,这对我来说似乎违反直觉。以下面的代码为例:
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 的实现,我发现迭代器缓存了下一个节点/值(在其 Advance() 方法中)。此缓存将跳过在 iterator.next() 被调用后立即创建的任何下一个项目。为什么它会贪婪地缓存下一项,而不是等到调用 Iterator next() 方法后再推进下一项?