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
競爭監視器鎖來實現執行緒同步。
關鍵點:synchronizemap
或concurrenthashmap
。
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 命令列,本文不是介紹某些命令的用法,而是說明一些簡單卻特別容易讓...