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)
型 参考代码:
static inline intptr_t get_next_hash(Thread * Self, oop obj) {
intptr_t value = 0 ;
if (hashCode == 0) {
// This form uses an unguarded global Park-Miller RNG,
// so it's possible for two threads to race and generate the same RNG.
// On MP system we'll have lots of RW access to a global, so the
// mechanism induces lots of coherency traffic.
value = os::random() ;
} else
if (hashCode == 1) {
// This variation has the property of being stable (idempotent)
// between STW operations. This can be useful in some of the 1-0
// synchronization schemes.
intptr_t addrBits = cast_from_oop<intptr_t>(obj) >> 3 ;
value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
} else
if (hashCode == 2) {
value = 1 ; // for sensitivity testing
} else
if (hashCode == 3) {
value = ++GVars.hcSequence ;
} else
if (hashCode == 4) {
value = cast_from_oop<intptr_t>(obj) ;
} else {
// Marsaglia's xor-shift scheme with thread-specific state
// This is probably the best overall implementation -- we'll
// likely make this the default in future releases.
unsigned t = Self->_hashStateX ;
t ^= (t << 11) ;
Self->_hashStateX = Self->_hashStateY ;
Self->_hashStateY = Self->_hashStateZ ;
Self->_hashStateZ = Self->_hashStateW ;
unsigned v = Self->_hashStateW ;
v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
Self->_hashStateW = v ;
value = v ;
}
value &= markOopDesc::hash_mask;
if (value == 0) value = 0xBAD ;
assert (value != markOopDesc::no_hash, "invariant") ;
TEVENT (hashCode: GENERATE) ;
return value;
}
3条答案
按热度按时间6l7fqoea1#
hashCode
合约规定,除其他事项外,如果根据
equals(Object)
方法,两个对象相等,则对这两个对象中的每一个调用hashCode
方法都必须产生相同的整数结果。所以,不,让它随机是一个坏主意。
hiz5n14c2#
基本答案
在典型的用例中,您希望检索的不是用于将其插入到散列集合中的相同(就标识而言)键对象,而是逻辑上等效(就相等而言)的对象。
因此,您希望下面的代码在Map中查找元素
字符串
如果hashCode完全基于随机数,那么k1和k2具有不同的哈希值,因此可能会指向HashMap的不同桶。
我们证明了对于实现
equals
的对象,随机hashCode是一个糟糕的想法。这是哈希码合约部分背后的原因:如果根据equals(Object)方法,两个对象相等,那么对这两个对象中的每一个调用hashCode方法必须产生相同的整数结果。
高级一点的部分:
Let's take a look at Object.hashCode implementation。请注意,身份hashCode()实现依赖于JVM。
查看JDK源代码,
get_next_hash
提供了六种计算hashCode的方法:型
参考代码:
型
OpenJDK 7和OpenJDK 6都使用第一种方法,即随机数生成器。
OpenJDK 8将默认状态更改为5线程状态并结合xorshift。
注意,Object.hashCode的所有这些实现都与Object.equals一致(就散列代码契约而言)
总而言之,您将实现Object.hashCode背后的策略之一,但是如果您实现equals,则会冒着破坏契约的风险。
yqkkidmi3#
如果你什么都不做,只使用
Object.hashCode()
(对象的“内存地址”),那么你或多或少已经得到了你想要的东西。因此,您可以拥有任何类的HashMap/HashSet键。安全的
equals