前言
照着源码重新认认真真的流程过了一遍,主要说的是链表的插入过程,红黑树的过程没有讲,权当自己复习所用。
hashMap PUT 函数详细过程
- 在jdk1.8中,一进来只有一句话 return putVal(hash(key), key, value, false, true)。
- hash(key)函数就是 key为空则返回0,否则是key.hashCode ^ key.hashCode >>> 16
- hash值计算完了就进入到putVal中。
- 第一个if是判断table == null || tab.length == 0 .如果是则扩容。(初始化的时候是不立刻建表的)
- 第二个if中,先得到hash & length - 1下标,然后判断第一个节点是否为空,为空则直接生成第一个节点
- 第二个if对应的else,是putValue的核心逻辑,有两个大的if-else分支。
- 第一个if判断、第一个节点hash值是否与新节点hash值是否相等,key值是否相等,或者key != null && key.equals(k)。如果都相等了,执行e = p这个操作。
- 再是else if 如果p 是树节点,就进入到红黑树的插入逻辑
- 最后是一个else,在这里主要是一个for用来计数的,两个if判断
- 第一个if里面是判断下一个节点是不是null,是则将新建节点,p.next = newNode。在这个if里面还会判断我这条链上的节点是不是大于等于8个,是的话还要树化。如果table表的长度小于64就会进行扩容,不树化。
- 第二个if就判断下个节点的hash值,key值,key值的equals()方法是不是相等,相等就直接break了。这时e就是那个判断为相等的节点。
- 然后执行第二个大if-else分支。其实这第二个只有一个if语句
- 如果 e != null , oldValue = e.value。最后还把oldValue返回了。
- 再里面一个if,如果 !onlyIfAbsent || oldValue == null 这个onlyIfAbsent是一个参数,直接就是false。所以默认是可以替换的,执行e.value = value。这样就将旧值替换成新的值了。
- 之后执行afterNodeAccess(e),这是为了linkedHahMap服务的,毕竟是LRU,hashmap就是空方法了。
- 出来核心的else之后,先执行++modCount
- 再执行if(++size > threshold) resize();如果大小大于阈值,扩容
- 最后是执行afterNodeInsertion(evict)方法,还是给linkedHashMap用的。
- 最最后面,其实是return null。所以如果put的时候,发现返回值不是null了,那就是key值重复了。