/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
putVal
/**
* Implements Map.put and related methods
*
* @param hash hash for key key的hash值,会重复
* @param key the key
* @param value the value to put
* @param onlyIfAbsent if true, don't change existing value 为true当put时不会替换key对应的值(如果不存在还是添加)
* @param evict if false, the table is in creation mode.
* @return previous value, or null if none
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
//tab一个节点数组,保存节点
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
//第一次new Hash Map后,put时,会进行扩容,具体扩容默认值或者初始化设置的相关值(比如初始设置10,则扩容2^4=16。比如设置15,还是2^4=16)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
//当前(数组长度-1)&hash后作为index,一个新的节点保存在index的位置
tab[i] = newNode(hash, key, value, null);
else {
//如果在数组tab中的index位置存在元素了
//e保存这个存在的节点
Node<K,V> e; K k;
//if中给这个存在的节点赋值了
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
//if中比较当前元素hash相同,key相同,保存这个节点,在后面把值替换掉
e = p;
else if (p instanceof TreeNode)
//hashmap保存数据,按照数组+链表+红黑树的形式
//如果这个节点是一个红黑树,那就是把新加的节点放到树中
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
//如果这个节点不是红黑树,那就是一个链表了
for (int binCount = 0; ; ++binCount) {
//如果循环到最后发现新节点通链表中节点不匹配,就把节点加到最后
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
//节点加进入后,判断一下这个链表的大小是不是大于等于8
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
//如果大于等于8,就要尝试去把当前链表构成红黑树
//尝试中判断当前链表大小是不是大于等于64,如果是才会构成红黑树
treeifyBin(tab, hash);
break;
}
//这里,链表对应 于在tab中保存的下标是相同的即(tab数组大小-1)&hash相同
//同时判断key是否相同。
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
//如果新节点和当前链表中的某个节点匹配,break。这时候e保存的就是这个存在的节点
break;
p = e;
}
}
//e保存存在的节点,如果为空标识hashmap中不存在节点,已经新加进去了
//如果不为空,就会去判断onlyIfAbsent (是不是替换旧的value值),从而进行替换value
//然后返回旧的value。代码中调用的afterNodeAccess(e);就是一个空方法,在hashmap中没什么用,我认为。
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
//新增的时候修改次数增加,通arraylist相同,
++modCount;
//大小是否超出阈值,超出就会扩容。这里的size就是我们hashmap的size()得到的值
if (++size > threshold)
resize();
//空方法
afterNodeInsertion(evict);
return null;
}
putput方法 /** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * ...