zoukankan      html  css  js  c++  java
  • HashMap

    1.HashMap源码

    1.1 类Node代码

        HashMap内部存储的单元是Node,Node类源码如下:

    1.2 HashMap数据结构

       HashMap数据结构是由Node数组及每个数组元素都是单向链表组成的,结构如下图:

      1.3  HashMap get操作  

      get操作就是根据key找到value值。首先key算出hash值,然后调用getNode方法找到value。

    ​ 

       已知HashMap table长度为n,n为2的m次方,即n=2^m,  然后通过hash算法(n-1)&hash算出下hash的二进制低m位作为table的index值,

      从而索引到Node节点,判断此节点hash值和查找的key的值以及key是否相等,相等的话继续沿着此链表查找,知道查找到满足前两个条件

      返回此Node节点,否则返回空。当节点数超过7个,链表转化为红黑树存储,查询就在此红黑树上进行。

     

    1.4 HashMap put操作

       HashMap put操作插入对应的key和value。同样先算出key的hash值,然后调用putVal方法。

    putVal方法,同样首先根据hash(key)&(n-1)取得hash值二进制低m位找到index,这样的散列算法使key比较均匀的分布在各个桶里,找到

    index索引到Node节点,如果为空,直接put在此节点,否则判断是否是红黑树,如果是则找到红黑树部分的节点则直接put,否则查找

    链表中下一个Node节点的key值和hash等于插入的key和hash值的话直接更新Node节点的value值,否则找到Node节点为NULL的节点,

    判断链表个数是否超过阈值7,超过链表转换为红黑树,不超过在链表new 新出的节点,然后判断HashMap的节点数是否大于阈值

    (负载因子*table的长度),大于的话resize扩容,否则不扩容。

    put方法示意图如下:

    1.5 HashMap resize操作

    HashMap resize方法首先计算出新的HashMap的容量newCap和新的threshold newThr。判断旧的map容量oldCap大于0并且大于最大容量,

    则newThr设置为整形最大值,如果oldCap小于最大容量,则newCap扩大一倍,newThr也扩大一倍,当oldCap<=0&&oldThr>0更新newThr

    等于oldThr,当oldCap<=0&&oldThr<=0时newCap设置为默认值,newThr设置为默认值(负载因子*16),当newThr=0时重新计算newThr的值。

    计算完newCap和newThr后,开始HashMap的重新散列,因为Map的length(oldCap)发生变化,数据分布hash方法(length-1)&hash计算出来的索引值

    有可能会变化,所以数据需要重新分布。方法是:先便利table数组,分别对数组元素对应每个链表执行rehash。如果链表只有一个节点,则只用计算

    此节点对应的新的下标直接赋值即可,如果对应是红黑树,按照红黑树的逻辑去执行,如果是链表,则遍历每个链表,对应对一个节点重新计算出index,

    jdk设计精巧体现在这里:因为hash方法(n-1)&hash,所以对于同一个key值,hash值一样,唯一的不同就是长度n,假设n是2的m次方,HashMap扩容之后

    n扩大两倍,m加1,所以(n-1)&hash由之前的二进制取低m位变成了取低m+1位,前m位都是一样的,所以差别是第m+1位和1与计算后的结果,有两种情况

    一是0,这种情况和扩容之前的取低m位一样,所以index也是一样,另一种情况是1,这种情况相当于2^m+扩容之前的index,第m+1位数字也可以用oldCap&hash

    计算出等于0索引值不变,等于1索引值+2^m。所以链表就相应拆成两部分,一部分是索引等于index,一部分等于index+2^m。



    PS:初始化长度:

    因为Java规定了static final 类型为静态类变量 int 类型。int类型限制了该变量的长度为4个字节共32个二进制位,最高位是符号位。

  • 相关阅读:
    基于Docker的Mysql主从复制搭建
    Docker操作命令——查看、停止、删除容器
    Git命令
    未定义数组下标: 0
    zookeeper-3.4.14单机多端口集群搭建
    使用MAT分析dump文件定位程序问题
    intellij idea2019.1中文破解版安装
    vscode打造golang开发环境
    python项目开发环境模块安装记录
    shell用法
  • 原文地址:https://www.cnblogs.com/cjn123/p/12148356.html
Copyright © 2011-2022 走看看