为什么 ConcurrentHashMap 阻止空键和值?

2022-08-31 07:27:47

ConcurrentHashMap 的 JavaDoc 是这样说的:

类似但不同,这个类不允许用作键或值。HashtableHashMapnull

我的问题:为什么?

第二个问题:为什么不允许空值?Hashtable

我使用了很多HashMap来存储数据。但是当换成NullPointerExceptions时,我遇到了几次麻烦。ConcurrentHashMap


答案 1

来自ConcurrentHashMap的作者(Doug Lea):

ConcurrentMaps(ConcurrentHashMaps,ConcurrentSkipListMaps)中不允许空值的主要原因是,在非并发映射中可能几乎无法容忍的歧义无法适应。最主要的是,如果返回 ,则无法检测键是否显式映射到与键未映射。在非并发映射中,可以通过 检查此项,但在并发映射中,映射可能在调用之间已更改。map.get(key)nullnullmap.contains(key)


答案 2

我相信,至少在某种程度上,这是为了让你组合并形成一个单一的调用。如果映射可以保存 null,则无法判断是否返回 null,因为该值没有键,或者只是因为该值为 null。containsKeygetget

为什么这是一个问题?因为自己没有安全的方法可以做到这一点。取以下代码:

if (m.containsKey(k)) {
   return m.get(k);
} else {
   throw new KeyNotPresentException();
}

由于 是 并发映射,因此 可能会在 和 调用之间删除键 k,从而导致此代码段返回表中从未存在的 null,而不是所需的 null。mcontainsKeygetKeyNotPresentException

通常,您可以通过同步来解决此问题,但是使用并发映射当然不起作用。因此,必须更改 的签名,而以向后兼容的方式执行此操作的唯一方法是防止用户首先插入 null 值,并继续将其用作“找不到键”的占位符。get


推荐