HashMap源碼

public V put(K key, V value) {
   if (table == EMPTY_TABLE) {
       inflateTable(threshold);
   }
   if (key == null)
       return putForNullKey(value);
   int hash = hash(key);
   //找下標
   int i = indexFor(hash, table.length);
   for (Entry<K,V> e = table[i]; e != null; e = e.next) {
       Object k;
       //如果該key已經存在,覆蓋並返回舊value
       if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
           V oldValue = e.value;
           e.value = value;
           e.recordAccess(this);
           return oldValue;
       }
   }

   modCount++;
   //如果 沒有該key,則增加節點
   addEntry(hash, key, value, i);
   return null;
}

void addEntry(int hash, K key, V value, int bucketIndex) {
   //校驗map容量,如果size大於閾值,擴容
   if ((size >= threshold) && (null != table[bucketIndex])) {
       //擴容
       resize(2 * table.length);
       hash = (null != key) ? hash(key) : 0;
       bucketIndex = indexFor(hash, table.length);
   }
   //直接創建節點
   createEntry(hash, key, value, bucketIndex);
}

void resize(int newCapacity) {
   Entry[] oldTable = table;
   int oldCapacity = oldTable.length;
   if (oldCapacity == MAXIMUM_CAPACITY) {
       threshold = Integer.MAX_VALUE;
       return;
   }

   Entry[] newTable = new Entry[newCapacity];
   //rehash,重新放節點
   transfer(newTable, initHashSeedAsNeeded(newCapacity));
   table = newTable;
   threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}


void transfer(Entry[] newTable, boolean rehash) {
   int newCapacity = newTable.length;
   for (Entry<K,V> e : table) {
       while(null != e) {
           Entry<K,V> next = e.next;//如果併發,此處一線程掛起,會引起節點循環引用,所以hashMap不安全
           if (rehash) {
               e.hash = null == e.key ? 0 : hash(e.key);
           }
           int i = indexFor(e.hash, newCapacity);
           e.next = newTable[i];
           newTable[i] = e;
           e = next;
       }
   }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章