【面試題集】hashcode相等的兩個類一定相等麼,反之呢

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一般是內存地址,但也不一定。

品茗IT-面試題集-首發

如果大家正在尋找一個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隨機數算法,使用位移和異或運算生成隨機數的方法;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章