如何解决随机整数作为hashCode
在构造函数中生成一个随机数并从hashCode
方法返回此值是个好主意吗?
可能会发生冲突,但这在编写自己的hashCode
方法时适用。那有什么缺点呢?
在HashMap中使用此对象时,它将与随机数一起作为哈希存储,然后由该对象检索。如果发生冲突,将通过equals
解决。
解决方法
hashCode
contract尤其指出了
如果根据
equals(Object)
方法两个对象相等,则在两个对象中的每个对象上调用hashCode
方法必须产生相同的整数结果。
所以不,将其随机化是一个坏主意。
,如果您什么也不做,而使用Object.hashCode()
(对象的“内存地址”),那么您或多或少都有想要实现的目标。因此,您可以具有任何类的HashMap / HashSet键。
仍然安全equals
。
基本答案
在典型的用例中,您不希望使用与用于将其插入哈希集合中的键对象相同(就身份而言),而是要使用逻辑上等效的对象(就相等而言)进行检索
因此,您希望下面的代码在地图上找到元素
Key k1 = new Key("param1","param2");
Key k2 = new Key("param1","param2");
Value val1 = new Value();
map.put(k1,value);
Value val2 = map.get(k2);
如果hashCode仅基于随机数,则k1和k2具有不同的哈希,因此可能将您指向HashMap的不同存储桶。
我们表明,对于实现equals
的对象,随机hashCode是一个糟糕的主意。
这是hash code contract部分背后的原因:
如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
更高级的部分:
Let's take a look at Object.hashCode implementation。 请注意,身份hashCode()实现取决于JVM。
看看JDK的来源,get_next_hash
提供了六种计算hashCode的方法:
0. A randomly generated number.
1. A function of memory address of the object.
2. A hardcoded 1 (used for sensitivity testing.)
3. A sequence.
4. The memory address of the object,cast to int.
5. Thread state combined with xorshift (https://en.wikipedia.org/wiki/Xorshift)
OpenJDK 7和OpenJDK 6都使用第一种方法,即随机数生成器。
OpenJDK 8将默认值更改为5-与xorshift结合使用的线程状态。
请注意,所有这些Object.hashCode的实现都与Object.equals一致(就哈希代码协定而言)
总而言之,您将实现Object.hashCode背后的策略之一,但是如果实现均等,则冒着违反合同的风险。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。