HashMap原理分析-2(JDK1.7)

HashMap原理分析-2(JDK1.7)

提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!!



HashMap原理分析-2(JDK1.7)

上文提到HASHMAP(JDK1.7)在PUT的时候会发生冲突,而解决冲突的方式就是使用链表,那么我们假设HASHMAP存储结构如下图:
在这里插入图片描述

那么节点1和节点2组成了一个链表,那么现在如果再来PUT一个节点3,假设节点3也需要插在这个链表中,我们考虑链表的插入效率,将节点3插在链表的头部是最快的,那么就会如下图:
在这里插入图片描述

那么按照上图这种插入办法,会出现一个问题:

  1. 当我们需要get(节点2)时,我们先将节点2的key进行哈希然后算出下标,拿到下标后可以定位到数组中的节点1,但是发现节点1不等于节点2,所以不是最终的结果,但是节点1存在下一个节点,所以可以顺着向下的指针找到节点2。
  2. 那么当我们需要get(节点3)时呢,我们发现是找不到节点3的,所以当我们把节点简单的插在链表的头部是不行的。
    那HashMap是怎么实现的呢?
    HashMap确实是将节点插在链表的头部,但是在插完之后HashMap会将整个链表向下移动一位,移动完之后就会变成:
    在这里插入图片描述
    那么现在PUT的时候插入一个元素的思路就是:将新节点插在链表的头部,此时新节点就是当前这个链表的头节点,接下来把头节点移动到数组位置即可。

当我们在使用HashMap的时候,还可能会出现下面的使用方式:

HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("1", "2");
String value = hashMap.put("1", "3");
System.out.println(value);

第三行代码也是PUT,而这个时候在HashMap里会将value覆盖,也就是key=“1"对应的value最终为"3”,而第三行代码返回的value将会是2。

我们现在来考虑这个PUT它是如何实现的,其实很简单,第三行代码的逻辑也是先对"1"计算哈希值以及对应的数组下标,有了数组下标之后就可以找到对应的位置的链表,而在将新节点插入到链表之前,还需要判断一下当前新节点的key值是不是已经在这个链表上存在,所以需要先去遍历当前这个位置的链表,在遍历的过程中如果找到了相同的key则会进行value的覆盖,并且返回oldvalue。
好,写到这里其实对于HashMap的PUT的主要逻辑也差不多了,总结一下:

  1. PUT(key,value)
  2. int hashcode = key.hashCode();
  3. int index = hashcode & (数组长度-1)
  4. 遍历index位置的链表,如果存在相同的key,则进行value覆盖,并且返回之前的value值
  5. 将key,value封装为节点对象(Entry)
  6. 将节点插在index位置上的链表的头部
  7. 将链表头节点移动到数组上
    这是最核心的7步,然后在这个过程中还有很重要的一步就是扩容,而扩容是发生在插入节点之前的,也就是步骤4和5之间的。

那么关于JDK1.7里HashMap的扩容时会出现“死锁”问题的(循环链表),我们下篇文章继续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值