我创建了一个 iterator() ,然后在迭代之前从映射中删除了第一个条目。我总是得到迭代器返回的第一个项目。但是当我删除第二个或后续条目时,当前迭代器不会返回该条目。
从 map 中删除第一个条目的示例:
Map<Integer,Integer> m1 = new ConcurrentHashMap<>();
m1.put(4, 1);
m1.put(5, 2);
m1.put(6, 3);
Iterator i1 = m1.entrySet().iterator();
m1.remove(4); // remove entry from map
while (i1.hasNext())
System.out.println("value :: "+i1.next()); //still shows entry 4=1
输出是:
value :: 4=1
value :: 5=2
value :: 6=3
从 map 中删除第三个条目的示例:
Map<Integer,Integer> m1 = new ConcurrentHashMap<>();
m1.put(4, 1);
m1.put(5, 2);
m1.put(6, 3);
Iterator i1 = m1.entrySet().iterator();
m1.remove(6); // remove entry from map
while (i1.hasNext())
System.out.println("value :: "+i1.next()); //does not show entry 6=3
输出是:
value :: 4=1
value :: 5=2
为什么从映射中删除第一个条目没有反射(reflect)在迭代器中,但删除第二个或后续条目却反射(reflect)在迭代器中?
Iterators, Spliterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw ConcurrentModificationException.
这意味着,它的迭代器反射(reflect)了迭代器创建时哈希表的状态。 当我们向 Map 添加或删除条目时,迭代器会显示原始条目吗?
最佳答案
根据this迭代器和 split 器是弱一致的。 “弱一致性”的定义可以参见here :
Most concurrent Collection implementations (including most Queues) also differ from the usual java.util conventions in that their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal:
- they may proceed concurrently with other operations
- they will never throw ConcurrentModificationException
- they are guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect any modifications subsequent to construction.
这意味着创建迭代器之后所做的任何修改都可能会得到反射(reflect),但不能保证。这只是并发迭代器\ split 器的正常行为。
关于java - 为什么从 ConcurrentHashMap 中删除第一个条目不会立即反射(reflect)在迭代器中,但删除第二个或后续条目会立即反射(reflect)在迭代器中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61440727/