jdk1.8中hashmap源码分析

本文详细分析了JDK1.8中HashMap的实现原理,包括从JDK1.6到1.8的变化,如1.8引入红黑树减少查找时间。还探讨了HashMap的数组大小、put方法和get方法的实现细节,强调了寻址方法、扩容机制和冲突解决策略。
摘要由CSDN通过智能技术生成

jdk1.8中hashmap源码分析

本文以JDK 1.8.0_131源代码为例进行分析:

  • jdk1.6到1.8中hashmap的变化
  • hashmap的实现原理
  • 数组大小及相关参数规定
  • Hashmap的put方法实现
  • Hashmap的get方法实现

jdk1.6到1.8中hashmap的变化

  • JDK1.6,JDK1.7中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。

    这里写图片描述

  • JDK1.8中,HashMap采用位桶+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
    这里写图片描述

hashmap的实现原理

:采用的是“桶位”,即一个Node数组实现
这里写图片描述
Node节点的实现:主要包括了key、value以及key的哈希值和next指向一个节点。
这里写图片描述

数组大小及相关参数规定规定:

  • 所有的默认值:
    默认的数组初始容量:16
    这里写图片描述
    默认的最大容量:2的30次方
    这里写图片描述
    默认的负载因子:0.75
    这里写图片描述
    默认的链表转红黑树的节点数阈值:8
    这里写图片描述
    Hashmap扩容的节点数阈值threshold=capacity*load factor:
    这里写图片描述
  • 注意Hashmap中数组容量capacity的值总是2的n次方:
    当不是2的n次方时,会用下面的函数进行调整。
    这里写图片描述
    >>>表示无符号右移,无论是正数还是负数,高位通通补0。经过5次向右位移后,n一定会变成000..00111..11类型,即前部分均为0,后部分均为1.所以返回的调整后的容量为n+1,一定是2的n次方。

Hashmap的put方法实现:

这里写图片描述
这里写图片描述

说明:

  • 代码块1:如果Node数组为空,则通过resize()函数新建一个长度为capacity的数组,并赋值给table。

  • 代码块2:找到key的hash值在数组中的位置为i,即该hash表的寻址方法为i=(n-1)&hash。如果table[i]==null,则直接为该数组new一个Node,并存储key,value。
    (注意:此处的寻址方法很巧妙,实质上相当于是求hash%(n-1),但是位运算的效率更高。因为n总是 2 的倍数,假设
    hash=5,n=16, 那么hash&n-1将得到5;如果hash=6,n=16,那么hash&n-1将得到6……如果hash=15,n=16,那么hash&n-1将得到15;但是当hash=16,n=16时,那么hash&n -1将得到0了;当hash=17,n=16时,那么hash&n -1将得到1了……这样保证计算得到的索引值总是位于table数组的索引之内。)

  • 代码块3:如果table[i]!=null,并且table[i].key与要插入的key相等,则e=table[i],并通过代码块6直接更新table[i]的value。

  • 代码块4:如果table[i].next所连接的是红黑树,则将key,value插入后面的红黑树。

  • 代码块5:如果table[i].next所连接的不是红黑树,则说明table[i].next连接的是普通链表,则通过e=p.next,p=e,一直到p.next==null.再把要插入的key,value插入到p.next。相当于新节点插入到了链表的最后

  • 代码块7:通过size记录hashmap中元素的个数,如果size>threshold,则利用resize()对table数组进行扩容。
    这里写图片描述
    即,扩容过程为直接将table的capacity容量乘以2,并且阈值threshold也乘2

Hashmap的get方法实现:

这里写图片描述
这里写图片描述
说明:

  • 代码块1:如果table数组(也称为bucket桶)为null,或者数据的长度小于0,或者当对key的hash值进行寻址时,即i=(n-1)&hash,first=table[i],如果table[i]==null。则直接return
    null。
  • 代码块2:如果table[i]的key值与需要查询的目标key相等,则返回table[i]。注意:此处table[i].hash与key的hash值相同,所以必须通过key的equal方法来判断两个key是否相等,因此在当key应用于hashmap时必须同时实现hashcode和equal两个方法
  • 代码块3:如果table[i].next后面链接的是红黑树,则在红黑树中进行查找。
  • 代码块4:如果table[i].next后面链接的是普通链表,则在该链表中进行遍历,并通过key的equal方法查找key相同的节点,并返回。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值