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 負載...