1. 程式人生 > >HashMap原始碼學習小結

HashMap原始碼學習小結

HashMap基本知識

  1. 連結串列陣列,使用雜湊函式定位位置,連結串列的元素是Entry< key,value>
    這裡寫圖片描述
  2. 查詢效能O(1),增刪效能O(1)
  3. 非執行緒安全,使用modCount欄位實現快速失敗的功能
  4. 在table長度小於閾值(1 << 30)的情況下,能夠自動擴容
  5. 定位的演算法:
    1. 取key.hashCode進行hash函式運算,得出運算結果h
    2. 將h和table.length進行計算:h & (table.length - 1)
    3. 取table[index] 的連結串列,對key進行比較(hash值的比較,equal比較)
  6. 4個建構函式
    1. 使用預設 table大小和loadfactor
    2. 指定table大小
    3. 指定loadfactor
    4. 使用存在的HashMap

問題總結

  1. 能否儲存key為null的元素?
    可以,存在table[0]的連結串列裡
  2. HashMap啥時候resize table?
    當map中元素的總數量size大於threshold
  3. loadfactor的作用
  4. 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():