HashMap-源碼心得總結

 

HashMap的底層數據結構?

數組+鏈表+紅黑樹,默認容量=16(無參構造爲0,但put首次會給16),負載因子=0.75默認容量閥值=容量*負載因子=12,鏈表長度閥值(引入紅黑樹)=8;

HashMap的存取原理?

1)存,
容量爲0時,調用resize()初始化默認容量=16。拿key值對數組長度hash取hashcode,來決定存儲的數組索引位置,無衝突直接入數組。若有衝突,先判斷Key本身是否重複了,如果重複了,覆蓋舊的。如果不是這種衝突,則再判斷,當前尾入口是紅黑樹的話,直接插入;如果不是這種衝突,再判斷,是否要引入紅黑樹(鏈表長度閥值>8,引入紅黑樹,8時不加不減)。最後,,需要考慮下是否擴容(如果超過負載因子*容量的值,擴容向左位運算1位,重新hash所有值)

2)取
首先根據key值的Hash值進行數組方面的尋找,然後找到這個數組之後,判斷key是不是唯一,如果key唯一,則直接返回,如果不唯一,則使用equals進行Hash值的判斷,最後返回數據

Java7和Java8的區別?

java8之後鏈表有紅黑樹(log(n)效率快)

爲啥會線程不安全?

到put/get方法都沒有加同步鎖,多線程情況最容易出現的就是:無法保證上一秒put的值,下一秒get的時候還是原值,所以線程安全還是無法保證。

有什麼線程安全的類代替麼?

一般都會使用HashTable或者ConcurrentHashMap
HashTable我看過他的源碼,很簡單粗暴,直接在方法上鎖sychronized,鎖的有點過分了;
ConcurrentHashMap我看過他的源碼,銷威好點,直接在方法裏面的代碼塊上鎖sychronized;

默認初始化大小是多少?爲啥是這麼多?爲啥大小都是2的冪?

默認給16..因爲官方要求是2的次方,方便對key進hash運算取hashCode值時,做位運算,比普通運算快很多。要求是2的次方,16只是作者覺得合適。

HashMap的擴容方式?負載因子是多少?爲什麼是這麼多?

向左位運算一位(*2)。初始若用無參構造函數會默認給16.因爲官方要求是2的次方,方便對key進hash運算取hashCode值時,做位運算,比普通運算快很多。要求是2的次方,16只是作者覺得合適。

HashMap的主要參數都有哪些?

容量、負載因子,table就是node類型的數組,裏面放的數組元素可理解爲鏈表形。

HashMap是怎麼處理hash碰撞的?

不同的值hashcode相同時,會放入鏈表後面,1.8用尾插法,如果鏈表長度超過8還會放入紅黑樹(log(n)效率快)

hash的計算規則?

對數組長度進行hash

hash的爲什麼要重寫hashcode?

Object類equals默認比較兩個對象的內存地址,我們想把它重寫成對象值的比較
而hashcode是本地方法,hashcode是根據對象的內存地址經哈希算法得來的,不同的對象的內存地址和原來Object類equals是一樣道理,比較地址是不相同的,.hashcode就不同,我們要改寫hashcode方法,也比較其對象值
比如,Student類的重寫後的equals方法和hashcode方法,現在有兩個Student對象:
    Student s1=new Student("小明",18);    Student s2=new Student("小明",18);此時s1.equals(s2),重寫後一定返回true,不重寫hashcode就會不一樣。
不滿足hashcode規定的規則:兩個對象相等其哈希值一定相等

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