美文网首页
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