java - 为什么从 ConcurrentHashMap 中删除第一个条目不会立即反射(reflect)在迭代器中,但删除第二个或后续条目会立即反射(reflect)在迭代器中?

标签 java collections concurrenthashmap

我创建了一个 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)在迭代器中?

Java documentation说:

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/

相关文章:

java - Java 的集合接口(interface)和类层次结构做得不好吗?

java - 多线程环境下HashMap的使用,定时更新

java - ConcurrentHashMap迭代保证

java - 跟踪映射中的重复插入(多线程环境)

java - Vigenere 解密奇数

scala - 我什么时候应该在scala中使用 "new"?

java - 当所有字段(包括分隔符,但不包括年份)都是可选时,在 Java8 中解析 ISO 8601 日期

java - 通过值的索引获取Guava Multimap的key

java - 如何配置 log4j 以使用 JULAppender 将日志事件发送到 java.util.logging?

java - 如何从管道分隔的键/值列表中检索值?