HashMap原始碼學習小結
阿新 • • 發佈:2019-02-01
HashMap基本知識
- 連結串列陣列,使用雜湊函式定位位置,連結串列的元素是Entry< key,value>
- 查詢效能O(1),增刪效能O(1)
- 非執行緒安全,使用modCount欄位實現快速失敗的功能
- 在table長度小於閾值(1 << 30)的情況下,能夠自動擴容
- 定位的演算法:
- 取key.hashCode進行hash函式運算,得出運算結果h
- 將h和table.length進行計算:h & (table.length - 1)
- 取table[index] 的連結串列,對key進行比較(hash值的比較,equal比較)
- 4個建構函式
- 使用預設 table大小和loadfactor
- 指定table大小
- 指定loadfactor
- 使用存在的HashMap
問題總結
- 能否儲存key為null的元素?
可以,存在table[0]的連結串列裡 - HashMap啥時候resize table?
當map中元素的總數量size大於threshold - loadfactor的作用
- threshold 的作用
threshold = (int)Math.min(table.length * loadFactor, MAXIMUM_CAPACITY + 1);
用來控制hashMap中元素的總數量。當總數量size大於threshold 的時候,就需要進行擴容操作了。
主要原始碼
get方法:
get(key){
hash = hash(key.hashcode()); //計算出key的hash函式結果
for(Entry<k,v> e:table[indexForKey(hash,table.lenght) ; e!=null ; e=e.next()]){
if(hash == e.hash && ((k = e.key) == key || (k != null && k.equal(key)))){
return e.value;
}
}
return null ;
}
put方法:
定位方法類似get。找到位置,且沒有相同的key的情況下。新增一個,如果key相同就替換原來的value
涉及到table大小的調整
put(key,value):
if(table == EMPTY_TABLE)
{
inflateTable(threshold);
}
if(key == null){
return putForNullKey(value);
}
int hash = hash(key.hashcode()); //計算出key的hash函式結果
int index = indexFor(hash,table.length);
for(Entry<k,v> e:table[indexForKey(hash,table.lenght) ; e!=null ; e=e.next()]){
if(hash == e.hash && ((k = e.key) == key || (k != null && k.equal(key)))){
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash,key,value,index);
return null;
addEntry():