美文网首页
HashMap详解

HashMap详解

作者: jianshujoker | 来源:发表于2019-04-23 22:55 被阅读0次

是什么

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射

为什么需要它

HaspMap是O(1)的

写代码时,查找元素更简洁的写法(haspMap.get(key))

实现

存储结构

hashmap储存结构.png

简单说来就是 数组(hash桶)+链表+红黑树

如何找到位置

前面说了HashMap是O(1),那HashMap是怎么找到元素在hash桶中的坐标呢?

  1. 获取object hashcode
  2. 通过hashcode计算位置

    2.1hashcode与hashcode的前16位与取值

    2.2用前面hashcode计算的值与(数组长度-1)与计算得到所在hash桶下标

扩容

现在我们知道了HashMap的结构和如何决定元素下标,思考下HashMap长度是否是一成不变的呢?

长度变与不变我想到两个问题

1.如果长度是不变的,导致某个node一直添加元素,HashMap的复杂度不就变成了红黑树的复杂度lgn?

2.如果长度是改变的,那什么时候改变长度呢?

带着这2个问题去探寻HashMap,先说答案,HashMap的长度是改变的,长度改变即扩容与几个参数有关

1.int threshold; //要调整大小的下一个大小值(容量*加载因子)。容量默认是16

2.final float loadFactor;//哈希表的加载因子。默认为0.75

即当HashMap拥有的元素个数大于threshold,就进行扩容。

知道了上面这些扩容知识,又引发另外一个问题,扩容后,元素位置不是要进行一次重新计算?

HashMap针对这一点做了个巧妙的处理,长度是2的n次方,这样元素的位置要么不变,要么移动2的次幂位置

使用时注意事项

1.HashMap不是线程安全的

2.HashMap在多线程下可能会导致死循环

jdk1.7.0_79跟代码

死循环是因为jdk7插入元素是前插法,在resize时会进行反转链表,多线程下就造成了死循环;网上很多用3,5,7演示死循环示例,看jdk1.7.0_79的源码发现,不管怎么样都不可能造成死循环,因为1是在resize后才把元素加进去,2是因为resize判断的2个条件,要size大于阀值,并且放的元素的index里面已经有值

jdk1.8.0_201跟代码

死循环是多线程情况下在红黑树里面造成的死循环,具体原因,由于我还没弄懂红黑树,没搞清楚

相关文章

网友评论

      本文标题:HashMap详解

      本文链接:https://www.haomeiwen.com/subject/yjrupqtx.html