hashmap代码解析

一、hashmap数据结构

   1.hashmap的数据结构。它有两部分构成:横向的数组和纵向的链表。在向hashmap放入数据的时候,hashmap根据keyhashcode计算对应hash值,并根据hash值计算在数组中的位置。如果产生碰撞(其他key也存放在该位置),那么把新加入的值放入链表的队头。删除数据的时候,也是首先计算keyhash值,然后,找到对应的数组位置,遍历链表,根据key找到对应元素,然后删除。具体的添加和删除逻辑请参见后续章节。


                                          图1.hashmap数据结构

二、添加元素

  2.是添加元素代码。如果keynull,那么执行putForNullKey()方法。该方法负责把keynull的元素放置到下标为0的数组单元所对应的链表中。如果key不为null,那么根据keyhashcode计算hash值,并根据hash值计算需要放置的数组下标。图3.是计算下标的过程。根据下标找到数组单元(存放链表地址),然后遍历链表。如果在链表中发现与key相等的元素,那么直接用新的value覆盖老的value,并返回老的value。如果没有找到对应的元素,那么直接插入新的元素。

2.put元素


图3.计算数组下标

    4.就是添加新元素的代码。新建一个链表节点,把该节点作为头节点,把原有链表放入该节点的尾指针。并把keyhash值,key,以及value放入该节点。另外,要判断该hashmap是否需要扩容。如果size大于或者等于threshold,那么重新分配hashmap容量,新容量为原来容量的2倍。下节详细介绍hashmap的扩容机制。


                                                                图4.添加新的元素


三、hashmap扩容

  5.hashmap的扩容代码。首先判断原来的数组长度是否等于MAXIMUM_CAPACITY(最大容量,缺省值为1<<31)。如果等于该值,那么说明已经达到容量上限。这时,把threshold设置为最大整数,这样做的目的是不允许再被扩容(4中扩容的先决条件是size大于threshold,现在threshold取值最大整数,因此,size不可能再大于threshold,所以,也就会不会再执行扩容逻辑)。如果数组长度没有达到最大容量,那么实例化一个新的数组,容量是现有数组长度的两倍。然后,重新计算所有链表中各个元素在新数组上的“坐标”。并把threshold设置为装填因子与新容量的乘积,比如1000*0.75


                                    图5.hashmap扩容逻辑

    图6.就是重新计算各个元素“坐标”的逻辑。遍历每一个链表,根据链表中每个元素的hash值计算需要放置该元素的新数组下标。找到对应的新数组下标后,在该下标对应的新数组单元中放入指向该元素的指针,并把新数组单元原来的内容放入该元素的next指针(其实就是增加链表头节点逻辑)


                                                                 图6.重新计算各个元素”坐标”

四、删除元素

   7和图8是删除元素的代码。根据keyhashcode计算hash值。如果keynull,那么hash值为0。根据hash值计算数组下标。找到下标对应的数组单元,遍历该数组单元对应的链表。找到与key匹配的元素,从链表中删除该元素。如果删除成功,返回删除元素的引用,否则,返回null


                                                                                                                         7. 删除元素

8.具体删除逻辑

五、hashmap初始化

   最后,我们聊下hashmap初始化。Hashmap缺省的初始化容量为16。可以在实例化时,指定初始化容量和装填因子。注意:hashmap实例化的时候,并不一定按照你指定的容量进行初始化的。如果你指定的值是2的幂,那么按照指定值进行初始化。否则,取大于指定初始化值的2的幂的最小值为新的初始化值。

    这样做的目的是为了减少碰撞概率。我们看下计算数组下标的方法逻辑(如图3所示):h&(length-1)。由于初始化长度和扩容后长度都是2的幂,因此,长度减1后,所得整数的二进制位数都为1。比如:初始化值取8,那么8-1=77的二进制是111。一个整数与7相与得到的结果比与6相与得到的结果重复率要小。









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值