大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

面試題首頁 > HashMap面試題

HashMap面試題

001HashMap底層原理是什么?

在JDK1.6,JDK1.7中,HashMap采用數組+鏈表實現,而JDK1.8中,HashMap采用數組+鏈表+紅黑樹實現。以JDK1.7的為例,HashMap里面的每個元素都是通過鍵值對key,value形式存儲的。首先它會通過key來計算對應的哈希值,并把key,value,hash值,下一個元素的地址封裝成一個Entry對象;然后再通過讓哈希值求模的形式來確定Entry對象在數組中的位置。假設在數組的下標為2的位置,那么首先會看下標為2的位置上是不是空,如果為空就直接將Entry對象放到2位置;如果下標為2的位置不為空,則會發生哈希碰撞,這時候需要遍歷該位置元素下的鏈表,看看哈希值和key值是不是都相同,如果相等則覆蓋原來的元素,如果不相等則在頭節點追加元素形成鏈表形式。  

002HashMap的主要參數都有哪些?

DEFAULT_INITIAL_CAPACITY:默認的初始化容量,1<<4位運算的結果是16,也就是默認的初始化容量為16,容量大小需要是2的整數倍。
MAXIMUM_CAPACITY:容量的最大值,1 << 30位,2的30次冪。
DEFAULT_LOAD_FACTOR:默認的加載因子。
TREEIFY_THRESHOLD:因為jdk8以后,HashMap底層的存儲結構改為了數組+鏈表+紅黑樹的存儲結構(之前是數組+鏈表),剛開始存儲元素產生碰撞時會在碰撞的數組后面掛上一個鏈表,當鏈表長度大于這個參數時,鏈表就可能會轉化為紅黑樹(為什么是可能后面還有一個參數,需要他們兩個都滿足的時候才會轉化)。
UNTREEIFY_THRESHOLD:介紹上面的參數時,我們知道當長度過大時可能會產生從鏈表到紅黑樹的轉化,但是,元素不僅僅只能添加還可以刪除,或者另一種情況,擴容后該數組槽位置上的元素數據不是很多了,還使用紅黑樹的結構就會很浪費,所以這時就可以把紅黑樹結構變回鏈表結構,什么時候變,就是元素數量等于這個值也就是6的時候變回來(元素數量指的是一個數組槽內的數量,不是HashMap中所有元素的數量)。
MIN_TREEIFY_CAPACITY:鏈表樹化的一個標準,前面說過當數組槽內的元素數量大于8時可能會轉化為紅黑樹,之所以說是可能就是因為這個值,當數組的長度小于這個值的時候,會先去進行擴容,擴容之后就有很大的可能讓數組槽內的數據可以更分散一些了,也就不用轉化數組槽后的存儲結構了。當然,長度大于這個值并且槽內數據大于8時,那就轉化為紅黑樹吧。

003HashMap中1.7和1.8版本的區別?

004Java8中為什么要引進紅黑樹,是為了解決什么場景的問題?

引入紅黑樹是為了避免hash性能急劇下降,引起HashMap的讀寫性能急劇下降的場景,正常情況下,一般是不會用到紅黑樹的,在一些極端場景下,假如客戶端實現了一個性能拙劣的hashCode方法,可以保證HashMap的讀寫復雜度不會低于O(lgN)。

005HashMap中為什么需要使用加載因子?

加載因子是用于表示數組中元素填滿的程度。加載因子默認值是0.75。如果不指明初始大小,數組默認大小即初始容量為16,加載因子loadFactor=0.75,默認初始容量是16*0.75=12。如果填充比為0.5則空間利用率比較低。如果填充比1,說明利用的空間很多,那么形成沖突的機會就會越大,鏈表也會邊長,這樣查找的成本就變高。

006HashMap中初始值為什么是16?

關于這個默認容量的選擇,JDK并沒有給出官方解釋,那么這應該就是個經驗值,既然一定要設置一個默認的2^n 作為初始值,那么就需要在效率和內存使用上做一個權衡。這個值既不能太小,也不能太大。太小了就有可能頻繁發生擴容,影響效率。太大了又浪費空間,不劃算。所以,16就作為一個經驗值被采用了。

007HashMap的長度可以為奇數嘛?

不可以。從key映射到HashMap的數組的對應位置時,會用到一個hash函數:index = HashCode(Key)&(Length - 1);
如果Length的長度為奇數,假設長度為15, Length-1轉換為二進制后為 1110 ,假設此時的hashCode為 101110001110101110 1011, 做&運算得出的index結果為: 101110001110101110 1010, 如果此時的hashCode為101110001110101110 1010,同樣的做&運算,發現得出啦相同的index。看似好像沒有很大的問題,因為我們在用hashmap的時候出現哈希值相等的情況還是有的。再看一種情況,如果長度為9,那么Length-1 轉換為二進制的結果為1000, 那么只要hashCode的最后三位不相同,計算出來的結果仍然是一樣的,那么此時的index會更容易出現,并且此時的index的最后三位永遠不會出現111的情況,這樣的話,不符合Hash算法的均勻分布原則。
假如長度為16,那么length-1對應的二進制位1111,那么計算哈希code的時不會影響index出現的概率,符合均勻分布的設計原則。 因此HashMap的長度一般為2^n, 默認的長度為16。

008HashMap中為什么需要擴容呢?

如果一直不進行擴容的話,鏈表就會越來越長,這樣查找的效率很低,因為鏈表的長度很大(當然最新版本使用了紅黑樹后會改進很多),擴容之后,將原來鏈表數組的每一個鏈表分成奇偶兩個子鏈表分別掛在新鏈表數組的散列位置,這樣就減少了每個鏈表的長度,增加查找效率。

009為什么HashMap的數組的大小是2的冪次方數?

JDK7的HashMap是數組+鏈表實現的,JDK8的HashMap是數組+鏈表+紅黑樹實現的;
當某個key-value對需要存儲到數組中時,需要先生成一個數組下標index,并且這個index不能越界。在HashMap中,先得到key的hashcode,hashcode是一個數字,然后通過hashcode & (table.length - 1) 運算得到一個數組下標index,是通過與運算計算出來一個數組下標的,而不是通過取余,與運算相比于取余運算速度更快,但是也有一個前提條件,就是數組的長度得是一個2的冪次方數。

010為什么說HashMap是線程不安全的?

HashMap在多線程并發時線程不安全,主要表現在下面兩個方面:
(1) 當向HashMap中put(添加)元素時導致的多線程數據不一致
比如有兩個線程 A 和 B ,首先 A 希望插入一個 key-value鍵值對到HashMap 中,它首先計算記錄所要落到的 hash 桶的索引坐標,然后獲取到該桶里面的鏈表頭結點,此時線程 A 的時間片用完了,而此時線程 B 被調度得以執行,和線程 A 一樣執行,只不過線程 B 成功將記錄插到了桶里面。假設線程 A 插入的記錄計算出來的 hash 桶索引和線程 B 要插入的記錄計算出來的 hash 桶索引是一樣的,那么當線程 B 成功插入之后,線程 A 再次被調度運行時,它依然持有過期的鏈表頭但是它對此一無所知,以至于它認為它應該這樣做,如此一來就覆蓋了線程 B 插入的記錄,這樣線程 B 插入的記錄就憑空消失了,造成了數據不一致的行為。
簡單來說就是在多線程環境下,向HashMap集合中添加元素會存在覆蓋的現象,導致了線程不安全。
(2) 當HashMap進行擴容調用resize()函數時引起死循環
HashMap在put的時候,插入的元素超過了容量(由負載因子決定)的范圍就會觸發擴容操作,就是rehash,這個會重新將原數組的內容重新hash到新的擴容數組中,在多線程的環境下,存在同時其他的元素也在進行put操作,如果hash值相同,可能出現同時在同一數組下用鏈表表示,造成閉環,導致在get時會出現死循環,所以HashMap是線程不安全的。
HashMap的線程不安全主要體現在下面兩個方面:
1.在JDK1.7中,當并發執行擴容操作時會造成環形鏈和數據丟失的情況。
2.在JDK1.8中,在并發執行put操作時會發生數據覆蓋的情況。

011HashMap如何存取數據的?

get(key)方法 :
● 首先獲取key的hash值,計算hash&(n-1)得到在數組中的位置first=tab[hash&(n-1)]
● 先判斷first的key是否與參數key相等,不等就遍歷后面的鏈表找到相同的key值返回對應的Value值即可
put(key,value)方法:
● 1)判斷鍵值對數組tab[]是否為空或為null,否則以默認大小resize();
● 2)根據鍵值key計算hash值,hash值再計算得到插入的數組索引i,如果tab[i]==null,直接新建節點添加,否則轉入3
● 3)判斷當前數組中處理hash沖突的方式為鏈表還是紅黑樹(check第一個節點類型即可),分別處理。

012HashMap觸發擴容條件?

1. hashMap默認的負載因子是0.75,即如果hashmap中的元素個數超過了總容量75%,則會觸發擴容
2. 如果某個桶中的鏈表長度大于等于8了,則會判斷當前的hashmap的容量是否大于64,如果小于64,則會進行擴容;如果大于64,則將鏈表轉為紅黑樹。

013HashMap如何有效減少碰撞?

1. 擾動函數:促使元素位置分布均勻,減少碰撞幾率
2. 使用final對象,并采用合適的equals()和hashCode()方法

014HashMap 和 ConcurrentHashMap的區別?

1)ConcurrentHashMap對整個桶數組進行了分割分段(Segment),然后在每一個分段上都用lock鎖進行保護,相對于HashTable的synchronized鎖的粒度更精細了一些,并發性能更好,而HashMap沒有鎖機制,不是線程安全的。(JDK1.8之后ConcurrentHashMap啟用了一種全新的方式實現,利用CAS算法。)
2)HashMap的鍵值對允許有null,但是ConCurrentHashMap都不允許。

015ConcurrentHashMap 和 Hashtable 的區別?

ConcurrentHashMap 結合了 HashMap 和 HashTable 二者的優勢。HashMap 沒有考慮同步,HashTable 考慮了同步的問題。但是 HashTable 在每次同步執行時都要鎖住整個結構。ConcurrentHashMap 鎖的方式是稍微細粒度的。ConcurrentHashMap 和 Hashtable 的區別主要體現在實現線程安全的方式上不同。
底層數據結構:JDK1.7的 ConcurrentHashMap 底層采用 分段的數組+鏈表 實現,JDK1.8 采用的數據結構跟HashMap1.8的結構一樣,數組+鏈表/紅黑二叉樹。Hashtable 和 JDK1.8 之前的 HashMap 的底層數據結構類似都是采用 數組+鏈表 的形式,數組是 HashMap 的主體,鏈表則是主要為了解決哈希沖突而存在的;
實現線程安全的方式(重要):① 在JDK1.7的時候,ConcurrentHashMap(分段鎖) 對整個桶數組進行了分割分段(Segment),每一把鎖只鎖容器其中一部分數據,多線程訪問容器里不同數據段的數據,就不會存在鎖競爭,提高并發訪問率。(默認分配16個Segment,比Hashtable效率提高16倍。) 到了 JDK1.8 的時候已經摒棄了Segment的概念,而是直接用 Node 數組+鏈表+紅黑樹的數據結構來實現,并發控制使用 synchronized 和 CAS 來操作。(JDK1.6以后 對 synchronized鎖做了很多優化) 整個看起來就像是優化過且線程安全的 HashMap,雖然在JDK1.8中還能看到 Segment 的數據結構,但是已經簡化了屬性,只是為了兼容舊版本;② Hashtable(同一把鎖) :使用 synchronized 來保證線程安全,效率非常低下。當一個線程訪問同步方法時,其他線程也訪問同步方法,可能會進入阻塞或輪詢狀態,如使用 put 添加元素,另一個線程不能使用 put 添加元素,也不能使用 get,競爭會越來越激烈效率越低。

016ConcurrentHashMap的并發度是什么?

程序運行時能夠同時更新ConccurentHashMap且不產生鎖競爭的最大線程數。默認為16,且可以在構造函數中設置。當用戶設置并發度時,ConcurrentHashMap會使用大于等于該值的最小2冪指數作為實際并發度(假如用戶設置并發度為17,實際并發度則為32)。

017ConCurrentHashmap 的key,value是否可以為null?

不行,如果key或者value為null會拋出空指針異常。

018ConcurrentHashMap使用什么技術來保證線程安全?

jdk1.7:Segment+HashEntry來進行實現的;
jdk1.8:放棄了Segment臃腫的設計,采用Node+CAS+Synchronized來保證線程安全;

019ConcurrentHashMap的get方法是否要加鎖,為什么?

不需要,get方法采用了unsafe方法,來保證線程安全。

020ConcurrentHashMap在JDK1.7和JDK1.8中實現有什么差別? JDK1.8解決了JDK1.7中什么問題?

HashTable : 使用了synchronized關鍵字對put等操作進行加鎖; 
ConcurrentHashMap JDK1.7:  使用分段鎖機制實現; 
ConcurrentHashMap JDK1.8: 則使用數組+鏈表+紅黑樹數據結構和CAS原子操作實現;

目錄

返回頂部
主站蜘蛛池模板: 国产91在线 | 欧美 | 精品国产日韩一区三区 | 女人18女人毛片 | 久久久久国产精品免费 | 天天摸夜夜摸爽爽狠狠婷婷97 | 久草视频免费看 | 国产91系列| 拍拍拍精品视频在线观看 | 亚洲精品国产综合一线久久 | 亚洲国产精品ⅴa在线观看 亚洲国产精品aa在线看 | 99资源网 | 久草视频在线免费看 | 国产精品高清久久久久久久 | 国产欧美亚洲另类第一页 | 免费在线看h | 色狠狠狠狠综合影视 | 欧美性性性性性色大片 | 在线久草视频 | 日韩在线中文 | 日韩精美视频 | 一级特黄特黄毛片欧美的 | 免费毛片播放 | 中文字幕有码在线观看 | 久久精品亚洲一级毛片 | 香蕉视频亚洲一级 | 中文字幕久久久久一区 | 欧美日韩在线视频播放 | 人人骚| 99热精品久久只有精品黑人 | 天天色天天射天天干 | 亚洲国产精品xo在线观看 | 国产精品亚洲片在线观看麻豆 | 国产精品你懂得 | 国内精品七七久久影院 | 99视频在线国产 | 欧美真人毛片动作视频 | 视频一区视频二区在线观看 | 久久久精品一区二区三区 | 日本人一级毛片视频 | 欧美日本高清视频在线观看 | 免费激情网址 |