HashMap 底層 原理(JDK 1 8)

2021-10-01 05:35:13 字數 2516 閱讀 4714

原來看過1.7的hashmap底層,1.8更新後也稍微看了一下,沒有進行仔細的總結,今天總結一下1.8底層的原理。本文只討論1.8的底層原理。以下全文為1.8版本的

對於hashmap的資料結構,是老生常談了,面試的時候經常會被問道。底層資料結構為陣列+鍊錶+紅黑樹,儲存的是node節點,紅黑樹是treenode。

在進行put操作的時候,會呼叫putval方法進行儲存,在呼叫方法的時候,key會進行雜湊計算。

public v put(k key, v value)
static final int hash(object key)
然後看putval 方法做了哪些操作

final v putval(int hash, k key, v value, boolean onlyifabsent,

boolean evict)

// 如果找到相等的 進行替換

if (e.hash == hash &&

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

break;

p = e;}}

v oldvalue = e.value;

if (!onlyifabsent || oldvalue == null)

e.value = value;

afternodeaccess(e);

return oldvalue;}}

// 對hashmap 的操作進行增加

++modcount;

// 判斷 增加後的陣列長度是否大於臨界值 臨界值為當前資料長的0.75

if (++size > threshold)

// 進行擴容

resize();

afternodeinsertion(evict);

return null;

}

hashmap陣列中儲存的節點是node,如果轉換成紅黑樹,節點就是treenode,可以自己看一看這兩個節點。然後來到主要的方法resize()。resize同時包含初始化陣列和擴容的功能。

final node resize() 

else if ((newcap = oldcap << 1) < maximum_capacity &&

oldcap >= default_initial_capacity)

newthr = oldthr << 1; // double threshold

}else if (oldthr > 0) // initial capacity was placed in threshold

newcap = oldthr;

else

if (newthr == 0)

// 新的擴容值

threshold = newthr;

// 建立陣列,初始化或者擴容

@suppresswarnings()

node newtab = (node)new node[newcap];

// 陣列新的拷貝

table = newtab;

// 如果陣列拷貝不是空,就是擴容,否則就是初始化 直接返回

if (oldtab != null)

else

} while ((e = next) != null); // 如果e節點下乙個不為null 繼續迴圈

// 判斷不為null

if (lotail != null)

if (hitail != null) }}

}}

// 返回樹

return newtab;

}

以上就是put 操作的過程。由此可知

1. 如果不進行put操作,hashmap底層不會進行建立陣列。put後進行初始化陣列,預設初始化陣列長度是16,擴容值為當前陣列長度的0.75。

(如果指定了長度,那麼擴容後,陣列長度也會是2的n次方,這樣是為了減少雜湊碰撞。)

2. 鍊錶長度如果大於等於7,(不是8),會進行轉換紅黑樹操作。在紅黑樹轉換方法裡,還會進行判斷陣列長度是否大於64,如果不大於,不轉換紅黑樹,進行擴容操作。否則進行轉換。(為了減少雜湊衝突)

3. 每次擴容,會進行當前陣列長度一倍的擴容,擴容值也進行一倍的增加。

get操作就不進行講解,就是通過key進行雜湊,計算在陣列的位置,然後如果是鍊錶,在煉表裡遍歷查詢。如果是紅黑樹,在紅黑樹裡遍歷查詢。

hashmap執行緒原因是會丟失資料,不會進行死迴圈。(也有可能是我測試的資料量太小)

具體原因是在擴容的時候。每次擴容,都會把當前節點拷貝出來,然後置null。如果a執行緒把節點資料獲取,然後置null;b執行緒就會獲取null資料,處理下乙個位置的資料,不管是哪個執行緒先完成擴容,都會丟失一部分資料。

而且不管是紅黑樹還是鍊錶,都會拆分成兩個,兩個執行緒同時拆分,同時賦值,也會造成後乙個執行緒會把前乙個執行緒的資料給覆蓋掉。

以上就是對hashmap的總結,如果有問題可以一起討論。

JDK1 8HashMap底層實現原理

預設初始容量 2 4 16 hashmap 底層陣列的長度總是 2 的 n 次方,這一點可參看後面關於 hashmap 構造器的介紹 當length 總是 2 的倍數時,h length 1 將是乙個非常巧妙的設計 假設 h 5,length 16,那麼 h length 1 將得到 5 如果 h ...

ThreadLocal 原始碼分析 jdk1 6

相信很多做分布式web開發的都封裝過這樣的乙個工具用來管理當前登入的使用者。在 裡面把使用者set進來 在controller 裡面get 出來使用 而且都是基於threadlocal 這個模板類來封裝的,出於好奇跟蹤進原始碼一 竟 這裡簡單寫個例子 public class baseloginco...

HashMap底層原理

1.hashmap概述 hashmap是基於雜湊表的map介面的非同步實現。此實現提供所有可選的對映操作,並允許使用null值和null鍵。此類不保證對映的順序,特別是它不保證該順序恆久不變。2.hashmap的資料結構 注意,迭代器的快速失敗行為不能得到保證,一般來說,存在非同步的併發修改時,不可...