随机整数作为 hashCode
Random integer as hashCode
在构造函数中生成一个随机数并从 hashCode
方法 return 这个值是个好主意吗?
有可能发生冲突,但这适用于编写您自己的 hashCode
方法。那么有什么缺点呢?
当在 HashMap 中使用此对象时,它将与随机数一起作为哈希存储,然后由相同的方法检索。如果有冲突,它们将由 equals
.
解决
If two objects are equal according to the equals(Object)
method, then calling the hashCode
method on each of the two objects must produce the same integer result.
所以不,让它随机是个坏主意。
基本答案
在典型的用例中,您不希望使用用于将其插入到哈希集合中的相同(就身份而言)键对象进行检索,而是使用逻辑上等效的对象(就身份而言)等于)。
因此,您希望以下代码在地图中查找元素
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:
部分背后的原因
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
更高级的部分:
Let's take a look at Object.hashCode implementation。
请注意,identity 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 背后的策略之一,但如果实施 equals,则有违约的风险。
如果你什么都不做,使用Object.hashCode()
(对象的“内存地址”),那么你或多或少已经达到了你想要的目的。因此,您可以拥有任何 class.
的 HashMap/HashSet 键
还有保险箱equals
。
在构造函数中生成一个随机数并从 hashCode
方法 return 这个值是个好主意吗?
有可能发生冲突,但这适用于编写您自己的 hashCode
方法。那么有什么缺点呢?
当在 HashMap 中使用此对象时,它将与随机数一起作为哈希存储,然后由相同的方法检索。如果有冲突,它们将由 equals
.
If two objects are equal according to the
equals(Object)
method, then calling thehashCode
method on each of the two objects must produce the same integer result.
所以不,让它随机是个坏主意。
基本答案
在典型的用例中,您不希望使用用于将其插入到哈希集合中的相同(就身份而言)键对象进行检索,而是使用逻辑上等效的对象(就身份而言)等于)。
因此,您希望以下代码在地图中查找元素
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:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
更高级的部分:
Let's take a look at Object.hashCode implementation。 请注意,identity 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 背后的策略之一,但如果实施 equals,则有违约的风险。
如果你什么都不做,使用Object.hashCode()
(对象的“内存地址”),那么你或多或少已经达到了你想要的目的。因此,您可以拥有任何 class.
还有保险箱equals
。