JavaSE---hash与Object.hashCode()

总结 

hashcode解决什么问题?

  1、集合的高效插入、删除、查找

    通过hashcode()计算出的值,可以快速 定位元素存储的位置

  2、哈希表结构的高效查找

    通过hashcode()计算出的值,可以快速 定位元素存储的位置 

 

System.identityHashCode和Object.hashCode()

  都可以用于获取对象的哈希码,但是它们之间有一些重要的区别。

    Object.hashCode():

      这个方法可以被子类覆盖(override),这意味着如果你使用的是一个自定义的对象,并且该对象的类重写了 hashCode 方法,那么调用 hashCode 会返回根据该类逻辑计算出的哈希码。这通常是基于对象的内容(即字段值)来计算的。

      如果没有被覆盖,Object.hashCode() 和 System.identityHashCode(Object x) 对于同一个对象通常会返回相同的值


    System.identityHashCode(Object x):

      这个方法不会被任何类的方法覆盖。它总是返回与对象的身份相关的哈希码,而不是内容。即使对象的 hashCode 方法被覆盖了,仍然会提供一个基于对象内存地址等底层信息的唯一标识符。

 

/**
     *  <Hash/散列函数>
     *      what
     *          把任意长度的输入 通过散列算法 变换成固定长度的输出,该输出就是散列值;
     *          这种转换是一种压缩映射(散列值的空间通常远小于输入的空间);
     *          不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值;
     *
     *          (一种将任意长度的消息压缩到某一固定长度的消息摘要的函数)
     *
     *      特点
     *          单向,不能反算;
     *
     *      应用
     *          加密 (md5+salt)
     */

  

/**
     *  <Object.hashCode()>
     *      what
     *          Returns a hash code value for the object.  返回一个对象的hash code值;
     *          This method is supported for the benefit of hash tables such as those provided by java.util.HashMap. 在哈希表中的java.util.HashMap有使用到hashCode方法;
     *
     *          Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
     *          在一个Java应用程序的执行过程中,无论在同一个对象上多次调用hashCode方法时,只要没有修改对象上的equals比较中使用的信息,hashCode方法必须始终返回相同的整数。
     *          This integer need not remain consistent from one execution of an application to another execution of the same application.
     *          在不同的Java应用中,同一个对象的hashCode值没必要一致;
     *
     *          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.
     *          ***如果2个对象 通过equals方法 返回true,这2个对象的hashCode方法 应该返回相同的int值;
     *
     *          It is not required that if two objects are unequal according to the  java.lang.Object#equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results.
     *          如果2个对象 通过equals方法 返回false,这2个对象的hashCode方法 应该返回不同的int值;
     *
     *          However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
     *          程序员 应该意识到 "不同对象生成不同的hash code值会提升哈希表的性能";
     *
     *      作用
     *          用于 哈希表的 查找
     *          (直接计算要查找内容的hashCode值,hashCode值就是 哈希表的下标索引)
     *
     *      存储位置
     *          对象头的MarkWord中
     *
     *  <hashCode与内存地址的关系>
     *      https://www.cnblogs.com/javastack/p/15441274.html
     *
     *      1、Hotspot hashCode实现:hotspot/src/share/vm/runtime/synchronizer.cpp
     *          0:随机数
     *          1:根据 对象内存地址 + 随机数 生成
     *          2:固定值1
     *          3:自增序列生成
     *          4:对象内存地址
     *          else:xor-shift 生成
     *
     *  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;
     * }
     *
     *
     */

  

posted on 2022-04-26 16:15  anpeiyong  阅读(31)  评论(0编辑  收藏  举报

导航