HashMap原始碼分析

2021-09-12 18:26:59 字數 2870 閱讀 1110

jdk1.8 之前 hashmap 由 陣列+鍊錶 組成的,陣列是 hashmap 的主體,鍊錶則是主要為了解決雜湊衝突而存在的(「拉鍊法」解決衝突).jdk1.8 以後在解決雜湊衝突時有了較大的變化,當鍊表長度大於閾值(預設為 8)時,將鍊錶轉化為紅黑樹,以減少搜尋時間。

jdk1.8 之前 hashmap 底層是 陣列和鍊錶 結合在一起使用也就是 鍊錶雜湊。hashmap 通過 key 的 hashcode 經過擾動函式處理過後得到 hash 值,然後通過 (n - 1) & hash 判斷當前元素存放的位置(這裡的 n 指的是陣列的長度),如果當前位置存在元素的話,就判斷該元素與要存入的元素的 hash 值以及 key 是否相同,如果相同的話,直接覆蓋,不相同就通過拉鍊法解決衝突。

所謂擾動函式指的就是 hashmap 的 hash 方法。使用 hash 方法也就是擾動函式是為了防止一些實現比較差的 hashcode() 方法 換句話說使用擾動函式之後可以減少碰撞。

// 序列號

private

static

final

long serialversionuid =

362498820763181265l;

// 預設的初始容量是16

static

final

int default_initial_capacity =

1<<4;

// 最大容量

static

final

int maximum_capacity =

1<<30;

// 預設的填充因子

static

final

float default_load_factor =

0.75f

;// 當桶(bucket)上的結點數大於這個值時會轉成紅黑樹

static

final

int treeify_threshold =8;

// 當桶(bucket)上的結點數小於這個值時樹轉鍊錶

static

final

int untreeify_threshold =6;

// 桶中結構轉化為紅黑樹對應的table的最小大小

static

final

int min_treeify_capacity =64;

// 儲存元素的陣列,總是2的冪次倍

transient node

table;

// 存放具體元素的集

transient set

> entryset;

// 存放元素的個數,注意這個不等於陣列的長度。

transient

int size;

// 每次擴容和更改map結構的計數器

transient

int modcount;

// 臨界值 當實際大小(容量*填充因子)超過臨界值時,會進行擴容

int threshold;

// 載入因子

先得到key.hashcode,然後在進行二次hash

static

final

inthash

(object key)

物件儲存的位置為(table.lenth-1)&hash(key)

}大抵的思路是先計算hash值然後在通過h&(table.lenth-1)得到桶的位置,然後再遍歷節點。

HashMap原始碼分析

public hashmap int initialcapacity,float loadfactor 2 接下來是重要的put方法,put方法用於將鍵值對儲存到map中,讓我們來具體分析一下。public v put k key,v value if key null 若key為null,則將va...

HashMap 原始碼分析

1 getentry object key 方法 final entrygetentry object key return null 根據key的hash值計算出索引,得到table中的位置,然後遍歷table處的鍊錶 for entrye table indexfor hash,table.le...

HashMap原始碼分析

public v put k key,v value if key null return putfornullkey value int hash hash key int i indexfor hash,table.length for entrye table i e null e e.nex...