hashmap是乙個底層用陣列+鍊錶實現的儲存kv鍵值對資料結構,它允許null鍵和null值。hashmap的儲存規則是,根據k的hashcode運算得到hash值,然後根據hash值運算得到下標,如果陣列中該下標沒有值就放入,有值就乙個乙個比較是否hash值相同並且equals也為true,如果是就用value更新原來的value,如果到達最後都沒找到相同的,就新增節點,在jdk1.8中進行了優化,當鍊表長度達到8時,就把鍊錶變為紅黑樹
hashmap繼承了abstractmap並重寫了裡面的方法。public class hashmapextends abstractmapimplements map, cloneable, serializable
hashmap實現了cloneable介面,可以被轉殖。
hashmap實現了serializable介面,可以被序列化。
//預設初始化容量16
static final int default_initial_capacity = 1 << 4;
//最大容量為2的30此方法
static final int maximum_capacity = 1 << 30;
//預設載入因子0.75
static final float default_load_factor = 0.75f;
//鍊錶轉成樹的閾值
static final int treeify_threshold = 8;
//樹轉換成鍊錶的閾值
static final int untreeify_threshold = 6;
//轉換成樹的最小容量閾值
static final int min_treeify_capacity = 64;
//儲存節點的陣列
transient node table;
//儲存的所有節點
transient set> entryset;
//儲存節點個數
transient int size;
//修改次數,用於迭代器的快速失敗
transient int modcount;
//擴容的閾值
int threshold;
//載入因子
final float loadfactor;
static class nodeimplements map.entry
public final k getkey()
public final v getvalue()
public final string tostring()
public final int hashcode()
public final v setvalue(v newvalue)
public final boolean equals(object o)
return false;}}
put(k,v)新增kv鍵值對//指定初始化容量和增長因子的構造器
public hashmap(int initialcapacity, float loadfactor)
//通過一定的演算法得到2的n次方近似於這個數
static final int tablesizefor(int cap)
//指定初始化大小的構造器
public hashmap(int initialcapacity)
//無參構造器
public hashmap()
//使用map初始化構造器
public hashmap(map extends k, ? extends v> m)
public v put(k key, v value)
static final int hash(object key)
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);
//如果是替換舊值,並沒有修改modcount
return oldvalue;}}
++modcount;
if (++size > threshold)
//新增了元素大於閾值,進行擴容
resize();
afternodeinsertion(evict);
return null;
}//初始化或對陣列進行二倍擴容
final node resize()
else if ((newcap = oldcap << 1) < maximum_capacity &&
oldcap >= default_initial_capacity)//原容量擴大二倍小於最大容量 並且 原容量要大於等於預設的初始化容量
newthr = oldthr << 1; // double threshold
}else if (oldthr > 0) //用原來的閾值初始化陣列大小(構造的時候如果指定了初始化大小是使用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);
if (lotail != null)
if (hitail != null) }}
}}return newtab;
}
但是hashmap為什麼要有modcount這個屬性呢?既然不是執行緒安全的,那麼快速失敗的意義在哪兒呢?而且如果put方法是key已存在,只是將新值替換舊值,modcount並沒有改變,難道你在使用迭代器遍歷時,其他執行緒修改了值,不用快速失敗嗎?public v remove(object key)
final noderemovenode(int hash, object key, object value,
boolean matchvalue, boolean movable)
p = e;
} while ((e = e.next) != null);}}
if (node != null && (!matchvalue || (v = node.value) == value ||
(value != null && value.equals(v))))
}return null;
}
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...