HashMap JDK1 7原始碼分析

2021-09-14 02:43:14 字數 3840 閱讀 1460

hashmapjdk原始碼分析

建構函式

底層資料結構

基本屬性

擴容方式

預設值繼承關係

crud方式

基本屬性:

static final int default_initial_capacity = 1 << 4; // aka 16

雜湊表中陣列預設初始值大小為16

static final int maximum_capacity = 1 << 30;

雜湊表中陣列最大容量值

static final float default_load_factor = 0.75f;

預設的載入因子-》擴容使用

static final entry<?,?> empty_table = {};

transient entry table = (entry) empty_table;

static class entry

hashmap底層的實現是陣列+鍊錶實現:陣列中儲存的是乙個個entry實體,hash到同乙個索引位置的資料通過鍊錶鏈結起來

transient int size;

hashmap中儲存entry實體的個數

int threshold;

擴容的閾值=》capacity * loadfactor

final float loadfactor;

載入因子

繼承關係

public class hashmapextends abstractmapimplements map, cloneable, serializable
繼承了abstractmap(jdk1.2)、實現了map介面implements map,可以轉殖、可以序列化

建構函式

//指定初始容量、指定載入因子

public hashmap(int initialcapacity, float loadfactor)

//通過預設載入因子和預設容量初始化

public hashmap(int initialcapacity)

public hashmap()

//通過map集合來初始化當前集合

public hashmap(map<? extends k, ? extends v> m)

put方法新增元素

public v put(k key, v value)

//可以儲存key為null的情況

if (key == null)

return putfornullkey(value);

//key不為null

int hash = hash(key);

int i = indexfor(hash, table.length);

//遍歷該位置i下面的鍊錶:(判斷key是否存在,存在替換value,不存在建立新entry)

for (entrye = table[i]; e != null; e = e.next)

}modcount++;

addentry(hash, key, value, i);

return null;

}

插入key為null情況

key為null做特殊處理,儲存在table索引位0號位置

遍歷該位置下的鍊錶,檢視key為null的節點是否存在,存在即將value更新為傳入的value

若該鍊錶下不存在則建立新的entry節點插入該鍊錶

private v putfornullkey(v value) 

}modcount++;

addentry(0, null, value, 0);

return null;

} final int hash(object k)

h ^= k.hashcode();

h ^= (h >>> 20) ^ (h >>> 12);

return h ^ (h >>> 7) ^ (h >>> 4);

}static int indexfor(int h, int length)

length 16

1001 1111 0110 0110

0000 0000 0000 1111

0000 0000 0000 0110

==>6

void addentry(int hash, k key, v value, int bucketindex) 

createentry(hash, key, value, bucketindex);

}

擴容時機:當前儲存元素的個數size>=擴容閾值threshold時考慮擴容

擴容大小為2倍的陣列大小table.length(陣列要滿足2的指數級關係)

void resize(int newcapacity) 

entry newtable = new entry[newcapacity];

transfer(newtable, inithashseedasneeded(newcapacity));

table = newtable;

threshold = (int)math.min(newcapacity * loadfactor, maximum_capacity + 1);

}

建立新的table陣列,並且將原來集合上的元素全部進行hash,找到新的對應位置進行插入

void transfer(entry newtable, boolean rehash) 

int i = indexfor(e.hash, newcapacity);

e.next = newtable[i];

newtable[i] = e;

e = next;}}

}

void createentry(int hash, k key, v value, int bucketindex)

元素作為當前索引位置的頭部元素進行插入

獲取元素:

get():通過鍵值key來查詢value

public v get(object key)

1、判斷key是否為null,是則特殊處理,知道到0號索引位置查詢元素

2、先通過hash找到索引位置,通過索引位置找到當前鍊錶,通過判斷key是否相等找到value進行返回

final entrygetentry(object key) 

int hash = (key == null) ? 0 : hash(key);

for (entrye = table[indexfor(hash, table.length)];

e != null;

e = e.next)

return null;

}

remove:刪除元素

public v remove(object key) 

final entryremoveentryforkey(object key)

int hash = (key == null) ? 0 : hash(key);

int i = indexfor(hash, table.length);

entryprev = table[i];

entrye = prev;

while (e != null)

prev = e;

e = next;

}return e;

}

HASHMAP JDK1 7 最詳細原理分析(二)

昨天的部落格我解釋了hashmap jdk1.7 在put的時候會發生衝突,而解決衝突的方式就是使用鍊錶,那麼我們假設hashmap儲存結構如下圖 那麼節點1和節點2組成了乙個鍊錶,那麼現在如果再來put乙個節點3,假設節點3也需要插在這個鍊錶中,我們考慮鍊錶的插入效率,將節點3插在鍊錶的頭部是最快...

HashMap JDK1 8 原始碼剖析

jdk1.8相對於jdk1.6來說,區別在於1.8hashmap採用位桶 鍊錶 紅黑樹實現,當鍊表的長度超過閾值 treeify threshold 8 的時候,會將鍊錶轉化為紅黑樹進行儲存。1 hashmap的主要屬性 private static final long serialversion...

HashMap 1 7 原始碼講解

1 hashseed 用於鍵的雜湊碼計算上,用於減少雜湊衝突。通過下面所述的inithashseedasneeded方法來進行初始化 2 threshold 表示可以存放的最大量,它的值為loadfactory 陣列容量,但是存在最大值為1 30 1 即2 30 1 3 loadfactory 負載...