hashcode和equals
首先,我们打开Object类,找到public native int hashCode();
方法,看下它的注释是什么,翻译后大概是这样的:
- 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
- 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
- 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
- 在合理可行的范围内,Object类定义的hashCode方法的确为不同对象返回不同的整数。 (这通常通过将对象的内部地址转换为整数来实现,但是Java™编程语言不强制要求此实现技术。)
所以,结论就很明显了:
- hashCode相等的类,equals不一定相等;
- equals相等的类,hashCode必然相等;
- hashCode一般是内存地址,但也不一定。
如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。
hashcode的生成规则。
jdk8的openjdk源码地址:http://hg.openjdk.java.net/jdk8,其他版本也可以在这个网站查到。
openjdk:
- corba:不流行的多语言、分布式通讯接口
- hotspot:Java 虚拟机
- jaxp:XML 处理
- jaxws:一组 XML web services 的 Java API
- jdk:java 开发工具包
- langtools:Java 语言工具
- nashorn:JVM 上的 JavaScript 运行时。
在这里插入图片描述
在hotspot下的src/share/vm/runtime/synchronizer.cpp文件中,能看到hashcode生成源码:
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;
}
- hashCode == 0,此类方案返回一个Park-Miller伪随机数生成器生成的随机数;OpenJdk 6 &7的默认实现;
- hashCode == 1,此类方案将对象的内存地址,做移位运算后与一个随机数进行异或得到结果;
- hashCode == 2,此类方案返回固定的1;
- hashCode == 3,此类方案返回一个自增序列的当前值;
- hashCode == 4,此类方案返回当前对象的内存地址;
- hashcode >= 5,Marsaglia XORshift随机数算法,使用位移和异或运算生成随机数的方法;