public V put(K key, V value) { // 若是table引用指向成員變量EMPTY_TABLE,那麼初始化HashMap(設置容量、臨界值,新的Entry數組引用) if (table == EMPTY_TABLE) { inflateTable(threshold); } // 若「key爲null」,則將該鍵值對添加到table[0]處,遍歷該鏈表,若是有key爲null,則將value替換。沒有就建立新Entry對象放在鏈表表頭 // 因此table[0]的位置上,永遠最多存儲1個Entry對象,造成不了鏈表。key爲null的Entry存在這裏 if (key == null) return putForNullKey(value); // 若「key不爲null」,則計算該key的哈希值 int hash = hash(key); // 搜索指定hash值在對應table中的索引 int i = indexFor(hash, table.length); // 循環遍歷table數組上的Entry對象,判斷該位置上key是否已存在 for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; // 哈希值相同而且對象相同 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { // 若是這個key對應的鍵值對已經存在,就用新的value代替老的value,而後退出! V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } // 修改次數+1 modCount++; // table數組中沒有key對應的鍵值對,就將key-value添加到table[i]處 addEntry(hash, key, value, i); return null; }
key.hashcode ^ h >>> 16java
高16位和低16位作異或操做增長隨機性,減小哈希衝突算法
h & (length -1)數組
concurrentHashMap安全
哈希表爲何是線程不安全的this
Segment 可重入鎖 ReentranLock ,是一種數組鏈表結構線程