Java1.8HashMap一段註釋的解釋

/**
 * Computes key.hashCode() and spreads (XORs) higher bits of hash
 * to lower.  Because the table uses power-of-two masking, sets of
 * hashes that vary only in bits above the current mask will
 * always collide. (Among known examples are sets of Float keys
 * holding consecutive whole numbers in small tables.)  So we
 * apply a transform that spreads the impact of higher bits
 * downward. There is a tradeoff between speed, utility, and
 * quality of bit-spreading. Because many common sets of hashes
 * are already reasonably distributed (so don't benefit from
 * spreading), and because we use trees to handle large sets of
 * collisions in bins, we just XOR some shifted bits in the
 * cheapest possible way to reduce systematic lossage, as well as
 * to incorporate impact of the highest bits that would otherwise
 * never be used in index calculations because of table bounds.
 */
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

該段註釋在hash()方法上。

通過hashCode()方法,計算得到key的hash值,並將近右移16位使其高16位與原hashcode進行異或(hash值本爲32位的int類型)。

之所以需要右移16位,是因爲散列表的大小都是2的階乘,如果不將高位與低位進行異或將會造成持續的hash碰撞。

(原因在於當散列表足夠小的時候,在計算存放位置的時候,參與比較的將只有低位,那麼高位的hash碼將會失去意義,導致大量碰撞產生)

一個顯而易見的例子就是一批Float類型的數據將會在一個小數據量的散列表中造成持續碰撞。所以在這裏將會通過把高位下移的方式來轉換,這是一種對於速度和實用之間的妥協。

相比持續碰撞後採用樹來保存大量hash碰撞的數據,右移幾位進行異或的代價其實很小,也解決了高位的hash不會在小數據量的散列表中進行位置計算的問題。

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