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