演算法與資料結構 (八) HashMap原始碼

2022-08-21 01:51:08 字數 1841 閱讀 5928

static class nodeimplements map.entry

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;

}}

//以下**好像是為了linkedhashmap服務的

v oldvalue = e.value;

if (!onlyifabsent || oldvalue == null)

e.value = value;

afternodeaccess(e);

return oldvalue;}}

++modcount;

// 如果容量超了 就擴容

if (++size > threshold)

resize();

afternodeinsertion(evict);

return null;

}

**除了紅黑樹的部分引出兩個部分:1. 為什麼採取hash & 長度-1 的方式找陣列位置  2.  如何擴容

定容量的方法:

static final int tablesizefor(int cap)

對於建構函式中傳入的整數,進行如下操作。結論就是得到的數,是大於等於傳入值的最小 2 的冪。也就是傳入64 就是64 ,傳入127 就是 128。

這演算法想起來不好想,但看**還是好理解。對於65這種,減去1,就是 100 0000  第一次運算 是110 0000 第二次: 111 1000,結果變成1111111(全1) 最後加上1  必然是2 的整次冪。

這也解決了 hash運算為什麼用   hash & n-1,因為&的效率大於除法和取餘運算,而且由於是2的整次冪,按位與和取餘操作效果一樣,但是速度更快。

此外 node節點中的hash 值 ,是這樣得到的,也就是原來key hashcode高16位和hashcode亦或。為的是增加高16位的參與感,減少hash衝突,如果key的hashcode 是  0a01 0b01 0c01 如果直接進行 按位與操作,那麼他們都被對映到同乙個位置,而經過這麼一輪操作會,會減少hash碰撞的情況。

static final int hash(object key) 

而擴容主要是resize方法 主要是這段** ,新的陣列是舊的陣列的二倍,如下是舊的資料遷移到新陣列中

if (oldtab != null) 

else

} while ((e = next) != null);

if (lotail != null)

if (hitail != null)

}}

1 .hash值的演算法,鍵的hash值與 高16亦或,保留高位資訊

---對映下標值 &(容量-1)得到實際的

2.  保證容量是2的冪採取按位或  

3. .hashmap的結構 

在1.8做出的改變,陣列加紅黑樹 鍊錶大於8就會變樹,

變樹的代價比較高,所以還增加了乙個條件,就是陣列大小要大於64,否則採取擴容的方法,解決鍊錶過長的問題。

4.hashmap可以插入空值鍵

有單獨的方法,永遠插在第乙個鍊錶,也就是陣列下標為0的位置

5.遍歷方法 

map.entryset()   這是拿到了所有的鍵值對

keyset()    這個是拿到了所有的鍵值

6.併發下的問題

put()丟失更新

resize()也可能丟失更新

資料結構與演算法(八)

運算元入棧,然後碰到操作符出棧頂的兩個運算元,之後得到結果加到棧頂。def postfix evaluation postfix,operand stack 運算元棧 for i in postfix 1 若為運算元 字母 入棧 if97 ord i 122 i float join operand...

資料結構與演算法分析(八) BFS演算法

圖的組成 頂點 vertices 邊 edges 圖的一些概念 1.鄰接 adjacent v1和v2相連線 2.路徑 path 乙個頂點序列 3.圈 cycle 乙個頂點出現了兩次 圖的表示 1.鄰接矩陣 空間大,但是速度快 2.鄰接表 空間小,但速度慢 實現 實現的是無權圖 1.根據邊的數目確定...

資料結構與演算法(八)希爾排序

希爾排序 1.希爾排序的產生 希爾排序是由科學家donald l.shell提出的,希爾排序基於插入排序,並新增了一些新的特性,從而大大提高插入排序的執行效率。2.插入排序的缺陷,多次移動 參見 插入排序 假如乙個很小的資料在靠右端的位置上。那麼要將該資料排序到正確的位置上,則所有的中間資料都需要向...