DIY主題討論20:哈希碼的計算

DIY主題討論20:哈希碼的計算

1)自主選擇一個類,說明它hashCode方法的設計理念和代碼核心邏輯。
2) 舉例說明。

HashCode

hashCode意義
在編寫類的時候,如果覆蓋了Object的equals方法,那麼必須要覆蓋hashCode方法,並且如果兩個對象用equals方法比較返回true,那麼這兩個對象hashCode返回的值也必須是相等的,並且對於同一個對象,equals方法需要比較的屬性值沒有被修改,那麼每次調用hashCode返回的值應該是一致的。

hashCode的主要目的就是爲了提高諸如java.util.HashMap這樣的散列表(hash table)的性能,散列表(hash table)需要保證集合的不重複,每個新加入的元素都要跟已經存在的元素不相等,一個個equals顯然性能很差,所以引入hashCode。

hashCode方法的設計理念

  1. 重寫equals()而重寫hashCode(),重寫hashCode()而重寫equals()
  2. 將hashCode分爲兩種:單個類的hashCode和容器類(集合數組)的hashCode
  3. hashCode設計核心公式:s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1],乘法因子是31
  4. hash算法乘法因子需要時素數,且越大越好
  5. 乘法因子是31原因:計算機計算31比較快,31 * i = (i << 5) - i ,另一原因對超過5W個英文單詞做測試,在取31情況下,碰撞的次數都不超過7次
  6. hash算法設計理念核心是降低衝突率,不同對象的hashCode儘量不要相等

hashCode代碼核心邏輯(舉例——Arrays)

爲什麼重寫HashCode?

在Arrays重寫了long、int、short、char、byte、boolean、float、double、Object,8個基本類型和Object類型的hashCode,在這個類中我想是因爲可以提供每種類型的equals()比較方法而重寫hashCode,如果不重寫equals(),那麼Arrays是個數組對象,Object對象使用內存地址來作爲hashCode,兩個相同值的Arrays對象會應爲內存地址不同而不相等,因此需要重寫equals()方法,進而需要重寫hashCode方法。

HashCode方法邏輯

  1. 空Arrays的hashCode爲0,只有一個對象,且對象爲null的hashCode爲0
  2. 非空Arrays遍歷每個元素得到hashCode
  3. Arrays得出的hashCode與List得出的hashCode是一樣的
  4. Arrays.hashCode()會計算一維數組元素的hashCode,如果是多維數組,那麼需要遞歸進行hashCode的計算,使用Arrays.deepHashCode(Object[])方法。
  5. 循環內部基本計算公式 result = 31 * result + elementHash;

計算邏輯

  • 如果是long值,則elementHash = (int)(f ^ (f >>> 32))
  • 如果是int值,則elementHash = int值
  • 如果是short值,則elementHash = short值
  • 如果是char值,則elementHash = char值
  • 如果是byte值,則elementHash = byte值
  • 如果是boolean值,則elementHash = element ? 1231 : 1237,附註boolean的hashCode使用1231和1237
  • 如果是float值,則elementHash = Float.floatToIntBits(f)
  • 如果是double值,則elementHash = (int)(Double.doubleToLongBits(f) ^ (Double.doubleToLongBits(f) >>> 32));
  • 如果是Object值,則elementHash = element.hashCode()

long與double都使用了f ^ (f >>> 32)),因爲long與double都是64位,需要轉換爲一個int數字——32位

思考

在jdk源碼中,都有哪些類重寫類hashCode,爲什麼?
equals方法的設計理念和代碼核心邏輯?

參考

https://stackoverflow.com/questions/299304/why-does-javas-hashcode-in-string-use-31-as-a-multiplier
https://m.imooc.com/article/22958
https://blog.csdn.net/qq_21251983/article/details/52164403

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章