HashMap-JDK1.8

参考链接:HashMap在JDK1.8之前和之后的区别

JDK1.8之前

  • new HashMap(n)中的n为其容量
  • 元素插入使用头插法
  • 并发插入(resize时)会产生循环链表,在get一个不存在的元素时会导致死循环。参考:Java HashMap的死循环

JDK1.8之后

  • 元素使用尾插法
  • new HashMap(n)中的n最接近的2^m为其容量
  • 并发插入还是有问题,但不会产生死循环
  • 插入时数组长度>64,桶元素>8时,会树型化
  • 发生resize时,resize后,桶元素个数<=6的,都会被解树型化
  • 取模用与操作(hash & (arrayLength-1))会比较快,所以数组的大小永远是2的N次方。你随便给一个初始值比如17会转为32
  • resize实现逻辑参考:Java HashMap工作原理及实现

HashMap关于static final int UNTREEIFY_THRESHOLD = 6的分析

img.png

  • 遍历整个原始桶,把桶内数据分配到原桶新桶
  • 具体图解分析可以参考以下链接的第六点:Java HashMap工作原理及实现
    img_1.png
  • 判断新桶元素个数<=UNTREEIFY_THRESHOLD(也就是6),那么解开树型化
  • 所以,结论来说:只要是resize后,桶元素个数<=6的,都是链表

indexFor为什么要用h&(h-1)

  • 位运算快
  • 比方说h=16,不减1,那么算出来的结果全是0或16,这样会出现中间的槽完全不存东西

什么时候扩容

当前大小>当前容量*扩展因子0.75,且计算出来的下标的卡槽不为空。

作者

神奇宝贝大师

发布于

2017-04-19

更新于

2017-04-19

许可协议

评论