hashmap有关问题与计算
1.HashMap的存儲方式是數組加鏈表,主干是一個Entry數組。Entry是HashMap的基本組成單元,每一個Entry包含一個key-value鍵值對;當不同的key經過hash計算得出的index值相同時,就需要在數組里添加一個鏈表來存儲index相同的元素,HashMap的整體結構如下:
簡單來說,HashMap由數組+鏈表組成的,數組是HashMap的主體,鏈表則是主要為了解決哈希沖突而存在的,如果定位到的數組位置不含鏈表(當前entry的next指向null),那么對于查找,添加等操作很快,僅需一次尋址即可;如果定位到的數組包含鏈表,對于添加操作,其時間復雜度為O(n),首先遍歷鏈表,存在即覆蓋,否則新增;對于查找操作來講,仍需遍歷鏈表,然后通過key對象的equals方法逐一比對查找。所以,性能考慮,HashMap中的鏈表出現越少,性能才會越好。
2.需要注意的是,新來的Entry節點插入鏈表時,使用的是“頭插法”。之所以把新來的節點放在頭節點,是因為HashMap的發明者認為,后插入的Entry被查找的可能性更大,這就是HashMap的底層原理,
HashMap的默認初始長度是16,并且每次自動擴展或是手動初始化時,長度必須是2的冪
初始長度16是為了服務于從Key映射到index的Hash算法
從Key映射到HashMap數組的對應位置,會用到一個Hash函數,比如調用 hashMap.put("book", 0) ,插入一個Key為“book"的元素。這時候我們需要利用一個哈希函數來確定Entry的插入位置(index):
index = Hash(“book”)---->> index = HashCode(Key) & (Length - 1)//這里Key為book,Length是HashMap的長度
整個過程如下:
1)計算book的hashcode,結果為十進制的3029737,二進制的101110001110101110 1001。
2)假定HashMap長度是默認的16,計算Length-1的結果為十進制的15,二進制的1111。
3)把以上兩個結果做與運算,101110001110101110 1001 & 1111 = 1001,十進制是9,所以 index=9。可以說,Hash算法最終得到的index結果,完全取決于Key的Hashcode值的最后幾位。
假設HashMap的長度是10,重復剛才的運算步驟
?
單獨看這個結果,表面上并沒有問題。我們再來嘗試一個新的HashCode 101110001110101110 1011 :
再換一個HashCode 101110001110101110 1111 試試 :
雖然HashCode的倒數第二第三位從0變成了1,但是運算的結果都是1001。也就是說,當HashMap長度為10的時候,有些index結果的出現幾率會更大,而有些index結果永遠不會出現(比如0111)!
這樣,顯然不符合Hash算法均勻分布的原則。
反觀長度16或者其他2的冪,Length-1的值是所有二進制位全為1,這種情況下,index的結果等同于HashCode后幾位的值。只要輸入的HashCode本身分布均勻,Hash算法的結果就是均勻的。
(這點也涉及到了JAVA中hashCode()與equals()區別與作用:hashCode也可以用來比較對象是否相同,且效率高于equals,equals的效率很低下。但hashCode()并不是完全可靠,不同的對象也可能生成相同的hashcode,而equals是完全可靠的。
?所有對于需要大量并且快速的對比的話如果都用equal()去做顯然效率太低,所以解決方式是,每當需要對比的時候,首先用hashCode()去對比,如果hashCode()不一樣,則表示這兩個對象肯定不相等(也就是不必再用equal()去再對比了),如果hashCode()相同,此時再對比他們的equal(),如果equal()也相同,則表示這兩個對象是真的相同了,這樣既能大大提高了效率也保證了對比的絕對正確性!)
(hashCode值的計算方式:具體可以參考不同版本的jdk api內的 hashCode函數)
3.HashMap非線程安全
1)Hashmap在插入元素過多的時候需要進行Resize,Resize的條件是
HashMap.Size >= Capacity * LoadFactor。
2)Hashmap的Resize包含擴容和ReHash兩個步驟,ReHash在并發的情況下可能會形成鏈表環。
https://blog.csdn.net/wufaliang003/article/details/80219296
?
?
?
?
?
總結
以上是生活随笔為你收集整理的hashmap有关问题与计算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开发项目之考研计划_软件测试之项目测试计
- 下一篇: python达梦数据库_Python 封