JDK8的HashMap源码阅读(红黑树除外)

4 篇文章 0 订阅

HashMap底层是个Node[] 

成员变量:
        DEFAULT_INITIAL_CAPACITY:默认初始化默认长度 1<<4  1左移四位也就是16
        MAXIMUM_CAPACITY:最大长度   1<<30    1左移30位 也就是2的30次方  也就是1073741824(这个数字不好记,记得是2的30次方就行了,大概是10亿多)
        DEFAULT_LOAD_FACTOR:负载因子,默认是0.75,这个参数用来表示当hashmap的长度达到 DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR 后就会进行resize(扩容)操作
        TREEIFY_THRESHOLD : 默认是8,当桶上的链表数大于这个值是转红黑树。注意:桶的链表数(数组中某一元素的链表数),不是hashmap的长度
        UNTREEIFY_THRESHOLD:默认值是6,当桶上的链表数小于这个值的时候转换成链表
        MIN_TREEIFY_CAPACITY:默认值是64,最小树形化阈值,当hashmap的容量达到这个值时,才允许树形化,如果小于这个值直接扩容
        Node<K,V>[] table :存放元素的数组
        loadFactor:真正的负载因子,默认是DEFAULT_LOAD_FACTOR,可在创建hashmap的时候进行自定义 new HashMap(初始化长度,负载因子)
        threshold:长度的阈值,hashmap数组(table)的长度 * DEFAULT_LOAD_FACTOR负载因子
        
put方法步骤:
        1、如果hashmap值是空的,则将hashmap进行扩容(初始化成默认长度DEFAULT_INITIAL_CAPACITY,使用无参空构造构造方法创建的hashmap不会初始化数组)
        2、key的hash值与(长度-1)进行 &(与) 运算(长度默认都是2的倍数,长度减一后所有位数都是1,高位补0),因此用来确定key所在数组中的位置,在这里jdk1.8进行了优化 1.7之前是与长度进行取%(模)运算,结果是一样的,与运算效率更高
        3、如果数组的该位置为空,则创建Node 并将该node放入数组的对应位置
        4、如果数组相应的位置不为空:并且key已经存在,覆盖原有的元素
        5、如果数组对应的位置是红黑树,将元素添加到红黑树中
        6、否则数组是链表,在链表的尾部(node的next)进行添加元素,如果该数组的位置链表长度已经达到了TREEIFY_THRESHOLD的值,则将该数组对应位置的链表转换为红黑树
        7、如果key已经存在,返回旧值。
        8、如果长度大于负载因子,则进行扩容
        
resize方法(扩容方法):
        一、计算新的数组长度、阈值
            1、使用oldCap记录旧数组的长度,oldThr记录旧数组长度的阈值
            2、newCap为新数组的长度,newThr为新数组长度的阈值
            3、如果旧数组的长度大于0并且达到最大值,则将长度阈值设置为Integer的最大值 也就是2的31次方
            4、如果旧数组的长度大于0并且旧数组长度左移一位(也就是长度*2)后小于最大长度MAXIMUM_CAPACITY,并且大于等于默认长度16,newThr也有oldThr左移一位
            5、如果旧数组的长度阈值大于0,新数组的长度为旧的阈值,否则新数组的长度和阈值都为默认值(初始化的时候)
            6、如果新的数组长度和阈值有一个大于最大值MAXIMUM_CAPACITY,新的阈值就是Integer的最大值 也就是2的31次方
        二、创建新的数组
        三、将旧数组的值写入到新的数组
            1、如果数组某个位置只有一个元素,将其hash值与新数组长度-1进行与运算并放入新数组的相应位置
            2、如果是红黑树,重新初始化红黑树
            3、循环链表,元素的hash值与旧数组长度进行与运算,针对不同的值拼接对应的链表,值为0,说明扩容后新数组对应的位置也一样,将链表的头放入新数组的对应位置,如果值不为0(值为旧数组的长度),
                则对应新数组的位置为,旧数组的位置+就数组的长度
        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员老牛了laoliu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值