基础知识
1.7 : 数组+ 链表
1.8 : 数组 + 链表 + 红黑树
重要成员:
modCount:
记录了map新增/删除k-v对,或者内部结构做了调整的次数,其主要作用,是对Map的 iterator() 操作做一致性校验,如果在iterator操作的过程中,map的数值有修改,直接抛出ConcurrentModificationException异常。
put()
put 方法是有返回值的,oldValue或者null
put 主要分为四步骤:
- key为null的特殊处理 putForNullKey
-
a) HashMap中,是允许key、value都为null的,且key为null只存一份,多次存储会将旧value值覆盖;
b) key为null的存储位置,都统一放在下标为0的bucket,即:table[0]位置的链表;
c) 如果是第一次对key=null做put操作,将会在table[0]的位置新增一个Entry结点,使用头插法做链表插入。
-
- 计算table中 bucket的下标
- 指定目标bucket,遍历Entry结点链表,若找到key相同的Entry结点,则做替换
- 未找到目标Entry结点,则新增一个Entry结点
addEntry
判断是否超过阈值,超过阈值扩容,否则创建一个节点。
扩容 resize
扩容有两个核心点:
- 扩容后大小是扩容前的2倍;
- 所有元素重新计算hash值,进行数据搬迁,从旧table迁到扩容后的新table。 为避免碰撞过多,先决策是否需要对每个Entry链表结点重新hash,然后根据hash值计算得到bucket下标,然后使用头插法做结点迁移
** Index 计算
index = HashCode(Key) & (Length- 1)
感谢大神分享:https://juejin.im/post/5de85e05f265da33b50727f6