java - 对本例中 ConcurrentHashMap 和 HashMap 行为的区别感到困惑

标签 java java-8 java.util.concurrent

我正在尝试了解 ConcurrentHashMap 的工作原理。我找到了一个例子,但我无法理解。这是它的代码:

Map<String, Object> myData = new HashMap<String, Object>();
myData.put("A", 1);
myData.put("B", 2);
for (String key : myData.keySet()) {
    myData.remove(key);
}

这将在运行时抛出异常 ConcurrentModificationException

但是,这段使用 ConcurrentHashMap 的代码可以正常工作:

Map<String, Object> myData = new ConcurrentHashMap<String, Object>();
myData.put("A", 1);
myData.put("B", 2);
for (String key : myData.keySet()) }
    myData.remove(key);
}

有人可以向我解释为什么 ConcurrentHashMap 允许在 HashMap 抛出异常时删除键吗?谢谢

最佳答案

这只是 ConcurrentHashMap 的特性之一。引用文档:

Similarly, 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.

但是,

ConcurrentHashMap 并不是真的这样做来支持您的用例。这样做是为了允许一个线程中的迭代与其他线程中的修改同时发生。

如果这是您使用 ConcurrentHashMap 的唯一原因,那么您可能应该重新考虑,因为它比 HashMap 昂贵得多。你最好在像这样使用之前复制 key 集:

Map<String, Object> myData = new HashMap<String, Object>();
myData.put("A", 1);
myData.put("B", 2);
for(String key: myData.keySet().toArray(new String[0]))
    myData.remove(key); 

关于java - 对本例中 ConcurrentHashMap 和 HashMap 行为的区别感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54755650/

相关文章:

java - 收到致命警报 : handshake_failure when calling from Java 1. 8.0_162 到 Java 1.6.0_45-b06

java - CopyOnWriteArraySet 何时对实现线程安全的 HashSet 有用?

动态扩展线程数的 Java ExecutorService

java - 并发 Java 1.5+ 中的 Activity 对象模式

Java 读取 XML - 在 '<' 特殊字符处停止

java - 为什么静态字段被称为 "static"?

java - 更新 Maven 在 Eclipse 中从 Java JDK 1.8 恢复到 JavaSE -1.8

java - 从 hibernate 检索几何对象到 angular.js

java - 在 JavaFX 图表中添加一条线

java - 接口(interface)方法引用的注释信息