Java 为什么哈希表不允许空值?

Java 为什么哈希表不允许空值?,java,Java,我知道哈希表中不允许使用空键,因为必须在哈希表哈希代码中存储元素。但若密钥为null,它将无法计算null密钥的哈希代码。但我不明白Sun开发人员不允许空值的确切原因是什么 有人说put方法实现中有空值检查,这就是它抛出NullPointerException的原因。但我的问题是为什么要进行空值检查。背后有什么具体原因吗 我读了很多书,但没有得到满意的答案。有人说,如果有空值存在歧义,如果您尝试使用get()方法检索值,它将返回空值,而此空值是因为实际值为空或缺少键,这就是为什么为空且无法预测原

我知道哈希表中不允许使用空键,因为必须在哈希表哈希代码中存储元素。但若密钥为null,它将无法计算null密钥的哈希代码。但我不明白Sun开发人员不允许空值的确切原因是什么

有人说put方法实现中有空值检查,这就是它抛出NullPointerException的原因。但我的问题是为什么要进行空值检查。背后有什么具体原因吗


我读了很多书,但没有得到满意的答案。有人说,如果有空值存在歧义,如果您尝试使用get()方法检索值,它将返回空值,而此空值是因为实际值为空或缺少键,这就是为什么为空且无法预测原因。所以我需要带证明的针点答案。

如果你这样做,你会得到空值

hashtable.get("key")
并且“key”不在映射中,则不需要存储空值

如果您能够存储null,您将永远不会知道您拥有什么:null映射,或者这是一个缺少的映射

要成功地从哈希表中存储和检索对象 用作键的对象必须实现hashCode方法和equals 方法

Null不是对象,因此无法对其调用.equals()或.hashCode(),因此哈希表无法计算哈希以将其用作键


Hashtable containsValue(Object value)函数在值为null时抛出NullPointerException,因此对于值也不允许为null的情况,Hashtable被视为遗留代码。您应该使用
HashMap
,它允许值使用
null
,并且一个键可以是
null

编辑

经过更深入的研究,我可能有理由支持这样的决定<代码>哈希表已同步(而
哈希映射
未同步)

发件人:

与新的集合实现不同,
哈希表
是同步的。如果不需要线程安全实现,建议使用
HashMap
代替
Hashtable
。如果需要线程安全的高并发实现,则建议使用
ConcurrentHashMap
代替
Hashtable

正如您可以看到的那样,
Hashtable
的后继者不是我前面写的
HashMap
,而是
ConcurrentHashMap
。我很惊讶,
ConcurrentHashMap
不允许
null
。我开始挖掘,发现:

ConcurrentMaps(
ConcurrentHashMaps
ConcurrentSkipListMaps
)中不允许使用空值的主要原因是无法容纳非并发映射中几乎无法容忍的歧义。主要的一点是,如果
map.get(key)
返回
null
,则无法检测键是否显式映射到
null
,而键没有映射。在非并发映射中,您可以通过
map.contains(key)
检查这一点,但在并发映射中,映射可能在调用之间发生了更改

因此,
Hashtable
的作者可能与
ConcurrentHashMap
的作者有着相同的原因,在
HashMap
中,空值仍然被认为是一个错误的决定,
java-9
中新的
Map
类和静态工厂方法证明:

Map.of("test", null)

将抛出一个
numpointerException

读取put方法的实现。下载JDK并浏览代码我认为你的问题在StackOverflow帖子中描述得很好我认为你应该让SUN开发人员知道“确切的理由”是什么……尤其是如果你需要证据的话!问题在于价值,而不是关键。这个问题已经提到了你在这里陈述的事实。每一次否决都是值得赞赏的。我没有否决,但也认为这不是正确的答案,因为
HashMap
允许值为null。没关系,你从
Hashtable
HashMap
中以相同的方式获得值,在一个类中可以做到,在第二分钟,你不能。所以你的论点是不正确的。我同意你们不需要存储空值,但我不是NPE的参数。也许你们可以告诉我们什么是OP的参数?我提出了一个你不需要的理由。它与SUN开发人员无关。如果有人能向我解释,为什么这不是一个答案,那么我将不胜感激。@Simion你投了反对票(不是我的),因为你根本没有回答这个问题。即使按照您所说的,使用可能为空的键和值仍然是一个错误的决定静态方法的映射证明了这一点