Java 在计算哈希代码时,哈希集如何在没有NullPointerException的情况下记录null条目

Java 在计算哈希代码时,哈希集如何在没有NullPointerException的情况下记录null条目,java,collections,nullpointerexception,set,Java,Collections,Nullpointerexception,Set,我知道为什么每个集合中都允许空实例的所有这些奇怪的哲学原因 但与列表中不同的是,集合(甚至映射)元素的位置取决于元素本身所添加元素的hashcode(保留插入顺序的LinkedHashSet除外) 所以,在计算添加到集合中的元素的哈希代码时,如果该元素被假定为null,它不应该抛出NPE null.hashCode() 它是否有某种类型的空检查 首先我想 System.out.println(setReference)如果有空值,也应该生成NPE,但是经过相当多的研究,我发现调用的实际方法是st

我知道为什么每个集合中都允许空实例的所有这些奇怪的哲学原因

但与列表中不同的是,集合(甚至映射)元素的位置取决于元素本身所添加元素的hashcode(保留插入顺序的
LinkedHashSet
除外)

所以,在计算添加到集合中的元素的哈希代码时,如果该元素被假定为null,它不应该抛出NPE

null.hashCode()

它是否有某种类型的空检查

首先我想 System.out.println(setReference)如果有空值,也应该生成NPE,但是经过相当多的研究,我发现调用的实际方法是staticvalueOf(Object obj)而不是toString()方法 与java文档中所述内容相比,它是空安全的, 我终于清醒过来了

但这仍然困扰着我,我知道我对一些小细节有点痴迷,但我必须这么做,因为目前我正在准备OCAJP 8,所以我冒着降级的风险来得到可信的解释,因为我在java文档中没有找到任何与此相关的东西


因此,对于集合中的哪些操作是空安全的,我们需要一个全面的答案。

null
是显式处理的。如果查看
HashSet
的实现,它基本上是一个
HashMap
,其中所有键都指向相同的(虚拟)值。如果深入研究
HashMap
计算键的哈希代码的方法,您会发现这个方法(代码取自OpenJDK 1.8.0_92-b14,尽管我真诚地怀疑它在任何其他JDK中都会有所不同):


因此,长话短说,
HashSet
s和
HashMap
s显式地处理
null
s,并将其哈希值视为0。

提示:如果javadoc不够,请阅读源代码。那…怎么了。。。只是试一试?通常你会从自己的经历中学到更多;而不是要求其他人提供现成的摘要答案。感谢您提供的优雅答案,这正是我所需要的,因此null的哈希代码存储为0。:)
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}