HashMap的工作原理(wait publish)

  1. HashMap 的扩容机制
    1. initialCapacity:初始容量。指的是 HashMap 集合初始化的时候自身的容量。可以在构造方法中指定;如果不指定的话,总容量默认值是 16 。需要注意的是初始容量必须是 2 的幂次方。

    2. size:当前 HashMap 中已经存储着的键值对数量,即 HashMap.size()

    3. loadFactor:加载因子。所谓的加载因子就是 HashMap (当前的容量/总容量) 到达一定值的时候,HashMap 会实施扩容。加载因子也可以通过构造方法中指定,默认的值是 0.75 。举个例子,假设有一个 HashMap 的初始容量为 16 ,那么扩容的阀值就是 0.75 * 16 = 12 。也就是说,在你打算存入第 13 个值的时候,HashMap 会先执行扩容。

    4. threshold:扩容阀值。即 扩容阀值 = HashMap 总容量 * 加载因子。当前 HashMap 的容量大于或等于扩容阀值的时候就会去执行扩容。扩容的容量为当前 HashMap 总容量的两倍。比如,当前 HashMap 的总容量为 16 ,那么扩容之后为 32 。

    5. table:Entry 数组。我们都知道 HashMap 内部存储 key/value 是通过 Entry 这个介质来实现的。而 table 就是 Entry 数组

  2. Java 1.8 中 HashMap 的不同
    1. 在 Java 1.8 中,如果链表的长度超过了 8 ,那么链表将转化为红黑树;链表长度低于6,就把红黑树转回链表;
    2. 发生 hash 碰撞时,Java 1.7 会在链表头部插入,而 Java 1.8 会在链表尾部插入;
    3. 在 Java 1.8 中,Entry 被 Node 代替(换了一个马甲)。
  3. put过程
    1. 对Key求Hash值,然后再计算下标
    2. 如果没有碰撞,直接放入桶中(碰撞的意思是计算得到的Hash值相同,需要放到同一个bucket中)
    3. 如果碰撞了,以链表的方式链接到后面
    4. 如果链表长度超过阀值( TREEIFY THRESHOLD==8),就把链表转成红黑树,链表长度低于6,就把红黑树转回链表
    5. 如果节点已经存在就替换旧值
    6. 如果桶满了(容量16*加载因子0.75),就需要 resize(扩容2倍后重排)
  4. get过程
    1. 当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置
    2. 找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点
    3. 最终找到要找的值对象
posted @ 2020-12-08 16:51  乃颜先生  阅读(135)  评论(0编辑  收藏  举报