你必須知道的HashMap面試題

2021-09-04 17:46:51 字數 2475 閱讀 2118

hashmap基於hash原理,通過put()get()方法儲存和獲取元素。它內部使用陣列+鍊錶或紅黑樹的結構,通過hash運算找到bucket位置來儲存entey物件,通過equals()方法找到正確的鍵值對。hashmap使用鏈位址法來解決hash碰撞問題,當發生碰撞時,物件會儲存在鍊錶的下乙個節點處。

get()首先通過計算key的hash值找到在陣列中的下標,若下標處元素為空則直接返回null,否則判斷該下標處元素是否是要查詢的元素,是就直接返回,不是就判斷該元素節點是否為紅黑樹節點,是就進行紅黑樹節點的查詢,否則遍歷鍊錶進行查詢。

關鍵點:hashmap是在bucket中儲存鍵物件和值物件作為map.entry

通過map m = collections.synchronizemap(hashmap)實現同步。在synchronizemap中給hashmap的所有操作增加synchronized競爭監視器鎖來實現執行緒同步。

關鍵點:synchronizemapconcurrenthashmap

hashmap通過計算key的hash值來確定陣列位置,不同的key可能會產生相同hash值,因此會發生hash碰撞,在hashmap中採用鏈位址法來解決hash衝突,當發生碰撞是,將相同hash值的元素儲存在鍊錶的下乙個節點處。除此之外還有開放位址法,再雜湊法。

關鍵點:產生碰撞原因,乙個好的hash函式可以降低碰撞。

hashmap中預設的負載因子為0.75,當hashmap中陣列元素個數超過負載因子乘以陣列總容量時會發生擴容,將陣列擴充套件為原來的兩倍,對原陣列中的元素再進行hash運算,獲得在新陣列中的位置。

關鍵點:擴容!!!。

多執行緒條件下對於hashmap進行操作確實會存在同步問題,看網上說調整hashmap大小會導致在頭部新增元素從而避免尾部迴圈,然後就死迴圈了…其實我沒懂!!!

hashmap推薦使用不可變變數作為鍵,其中string最為常用,因為string是不可變的,也是final的,我們通過計算key的hash值在陣列中進行查詢,如果key是可變型別,那麼在插入和獲取時返回的hashcode不同,就無法正確獲得我們想要的物件。

可以,但是要確保這個物件重寫了hashcode()equals()方法,並且該物件插入map後就不再改變,只要遵循了這些,它就已經可以作為鍵了。

可以,並且推薦使用cocurrenthashmap。hashtable採用synchronized實現同步,對其中所有方法新增監視器鎖,問題在於,在乙個執行緒進行put操作時,其他執行緒無法獲得get或其他操作,而cocurrenthashmap採用分段鎖技術,比hashtable提供更強的執行緒安全。

擴容是是新建了乙個hashmap的底層陣列,而後呼叫transfer方法,將就hashmap的全部元素新增到新的hashmap中(要重新計算元素在新的陣列中的索引位置)。 很明顯,擴容是乙個相當耗時的操作,因為它需要重新計算這些元素在新的陣列中的位置並進行複製處理。因此,我們在用hashmap的時,最好能提前預估下hashmap中元素的個數,這樣有助於提高hashmap的效能。

當多個執行緒對hashmap就行put操作時,如果put的key相同會產生碰撞,那麼hashmap會將兩個key放在陣列的同一位置,其中乙個執行緒的key會被覆蓋。

當多個執行緒檢測到陣列需要擴容時,都會進行陣列中元素hash值的重新計算和資料複製,那麼也勢必造成最後只有乙個執行緒建立的陣列成功賦值給table。

使用執行緒安全的hashtable,當乙個執行緒訪問hashtable的同步方法時,其他執行緒會被阻塞。也就是說當乙個執行緒進行get操作,其他執行緒不能進行任何操作,效率很低。

使用collections.synchronizemap(hashmap)。但是它的效率也不高,不信去看原始碼,看完之後會發現它跟hashtable具有同樣的問題。

使用cocurrenthashmap

static

final

inthash

(object key)

hash通過計算key自身的hashcode()值,,返回的型別是int,為了減少碰撞產生的機率,將獲得的hashcode()的低16位與高16位右移16位相異或。

當key值為物件時必須要求重寫hashcode()equals()方法。因為預設的hashcode()使用的是該值在記憶體中的位址作為該值的hash值,如果兩個具有相同意義的物件進行比較時,由於其位址不同會導致計算出的hash值也不同。而重寫equals()可以確保兩個物件具有相同意義的屬性。

Linux世界你必須知道的

突然從windows世界轉向linux世界,也許剛開始或多或少都有點不太適應,慢慢地,也許你會發現linux的博大精深,最重要的是linux世界的很多東西都是free license,下面列舉一下linux世界你需要或必須知道的二三事。unix like 叫做 類unix 系統,主要指各種各樣的li...

你必須知道的關於tcp keepalive 設定

1.引數設定 檢視相關的引數 sysctl a grep tcp keepalive net.ipv4.tcp keepalive intvl 30 net.ipv4.tcp keepalive probes 2 net.ipv4.tcp keepalive time 160 設定相關的引數 sys...

關於 Linux shell 你必須知道的

我個人很喜歡使用 linux 系統,雖然說 windows 的圖形化介面做的確實比 linux 好,但是對指令碼的支援太差了。一開始有點不習慣命令列操作,但是熟悉了之後反而發現移動滑鼠點點點才是浪費時間的罪魁禍首。那麼對於 linux 命令列,本文不是介紹某些命令的用法,而是說明一些簡單卻特別容易讓...