Object-hashCode算法笔记

hashCode()是什么

Object的hashCode()通过JVM虚拟机来实现其算法,主要为对象计算出一个hash值,hash值可以先理解为当前对象在内存中存储的相对位置

hashCode()的作用及怎么用:
通过该hash值可以高效的对两个对象进行比较,比较逻辑如下:

	if (A.hash != B.hash){
        A != B
    }else {
        if (A.equals != B.equals) {
            A != B
        } else {
            A == B
        }
    }

辅助理解:
Object的hashCode算法会被很多基础类使用,比如HashMap中计算hash值,但在跟踪jdk 1.8源码时发现hashCode定义是native,所有就需要去扣hashCode源码(Object中hashCode的声明:public native int hashCode();)

在扣源码之前有些朋友误以为默认情况下,hashCode返回的就是对象的存储地址,事实上这种看法是不全面的,确实有些JVM在实现时是直接返回对象的存储地址,但是大多时候并不是这样,只能说可能存储地址有一定关联。下面是HotSpot JVM中生成hash散列值的实现:

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 = 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 = 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;
}

该实现位于hotspot/src/share/vm/runtime/synchronizer.cpp文件下。如上参考:浅谈Java中的hashcode方法

在有些情况下,程序设计者在设计一个类的时候为需要重写equals方法,比如String类,但是千万要注意,在重写equals方法的同时,必须重写hashCode方法。为什么这么说呢?

主要是Object原生的hash值可以理解为取的是对象地址,如果比较两个String的话,两个对象的地址一定不同,如果不重写hashCode两个对象一定不相同(相同的意思是内容相同,而不是同一个对象),故为了达到时两个对象内容相同的情况下hashCode相关,则需重写Object.hashCode();且保证只要元数据相同,则hashCode必须相同,不相同的元数据hashCode也可以相同

hash主要提供了一种快速查找的手段,但该手段同时会引入冲突问题,如何解决冲突问题的方法则将在后续阐述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值