为什么 ConcurrentHashMap 阻止空键和值?
ConcurrentHashMap
的 JavaDoc 是这样说的:
类似但不同,这个类不允许用作键或值。
Hashtable
HashMap
null
我的问题:为什么?
第二个问题:为什么不允许空值?Hashtable
我使用了很多HashMap来存储数据。但是当换成NullPointerExceptions时,我遇到了几次麻烦。ConcurrentHashMap
ConcurrentHashMap
的 JavaDoc 是这样说的:
类似但不同,这个类不允许用作键或值。
Hashtable
HashMap
null
我的问题:为什么?
第二个问题:为什么不允许空值?Hashtable
我使用了很多HashMap来存储数据。但是当换成NullPointerExceptions时,我遇到了几次麻烦。ConcurrentHashMap
来自ConcurrentHashMap
的作者(Doug Lea)::
ConcurrentMaps(ConcurrentHashMaps,ConcurrentSkipListMaps)中不允许空值的主要原因是,在非并发映射中可能几乎无法容忍的歧义无法适应。最主要的是,如果返回 ,则无法检测键是否显式映射到与键未映射。在非并发映射中,可以通过 检查此项,但在并发映射中,映射可能在调用之间已更改。
map.get(key)
null
null
map.contains(key)
我相信,至少在某种程度上,这是为了让你组合并形成一个单一的调用。如果映射可以保存 null,则无法判断是否返回 null,因为该值没有键,或者只是因为该值为 null。containsKey
get
get
为什么这是一个问题?因为自己没有安全的方法可以做到这一点。取以下代码:
if (m.containsKey(k)) {
return m.get(k);
} else {
throw new KeyNotPresentException();
}
由于 是 并发映射,因此 可能会在 和 调用之间删除键 k,从而导致此代码段返回表中从未存在的 null,而不是所需的 null。m
containsKey
get
KeyNotPresentException
通常,您可以通过同步来解决此问题,但是使用并发映射当然不起作用。因此,必须更改 的签名,而以向后兼容的方式执行此操作的唯一方法是防止用户首先插入 null 值,并继续将其用作“找不到键”的占位符。get