《JAVA API-集合》3 HashMap、HashTable、LinkedHashMap

一 HashMap的設計思路

1 存儲:數組+單鏈表 + 紅黑樹(jdk1.8)

(1)數組下標的計算:

// 計算hash值
int h;
(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16)
// i爲數組下標,n爲數組的容量
i = (n - 1) & hash

第一個計算的設計:通過官方解釋是jvm計算hashcode的低位計算產生衝突的概率大,所以取高位的16位計算

第二個計算的設計:通過&操作保證下標不會超過數組的下標

(2)如果hashcode相同判斷元素是否相同,如果不相同就放到單鏈表中,如果單鏈表的長度超過8個變爲紅黑樹

// 判斷元素相同的邏輯
if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;

2 擴容

(1)當數組數量超過 容量 X 0.75的時候擴展爲2倍

(2)擴容因子0.75:空間和時間的綜合,如果擴容因子太大導致碰撞的機率增大,也就是增長鏈表的長度,導致了查詢的時間變長;如果擴容因子太小,造成空間浪費

3 hashcode:看Object中的hashCode()方法可知,hashCode()的作用在於提升hash tables的性能。

4 String的hashCode():根據源碼最後可以得到一個多項式,其中的常數31是根據數學上的原理得來的,原因是不太大也不太小的素數相乘得到的數字產生碰撞的概率較小,所以String類型非常適合作爲key值。

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

二 HashTable

1 線程安全版的HashMap

2 存儲、擴容、hashcode的計算不同但是差不多

三 LinkedHashMap

1 用雙鏈表實現

2 查找的時間複雜度是O(n/2),因爲會判斷當前的index更靠近head還是跟靠近tail然後從更近的點開始查找

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