HashMap 扰动函数、负载因子、扩容链表拆分

1.扰动函数

在jdk8中,hashmap有这样一段代码,他叫扰动函数,目的是优化散列效果

static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

我们获取到的key.hashCode()哈希值,哈希的取值范围是[-2147483648, 2147483647],那我们能拿这个数来当作下表吗?很显然不太行,那就需要数组的大小做与运算,hashmap的初始数组大小是1 << 4 ,也就是16,那计算数组的下标同过与运算的方式获得,(16-1)&h。

1. 那么为什么我要使用这个扰动函数呢?我们不用扰动函数行不行?
使用扰动函数的目的就是为了优化散列,从而减少hash碰撞。

2. 那我们为什么选择数组长度要选择2的幂次方?
假如数组长度是8,那获取下标索引 (8-1)& h,数组长度就会出现一个0111除了高位以为都是1的特征,也是为了散列。

2.初始容量

  • hashmap初始容量大小是16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
  • 那我们都直到数组的长度是选择2的幂次方的,那假如我们传入的默认长度是17,那么就要找比初始值大的那个最小2的幂次方,2的5次幂32>17,那么传入17的默认容量大小就是32。

那么底层是有一段代码去支撑的:
在这里插入图片描述

static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

这个n|=n>>>1,2,4,8,16这个右移主要是把右边都填上1,假如我们输入的是17
在这里插入图片描述

3.负载因子

负载因子决定了什么时候进行扩容,为什么不等把所有数组中所有下标都用完之后在扩容呢?其实就是为了减少hash碰撞,从而提高效率。当负载因子设置0.75的时候,假设初始容量是16,那么当增加到13个数的时候,就会进行扩容操作。
在这里插入图片描述

4.扩容链表拆分

为什么扩容,因为数组长度不足了。那扩容最直接的问题,就是需要把元素拆分到新的数组中。拆分元素的过程中,原jdk1.7中会需要重新计算哈希值,但是到jdk1.8中已经进行优化,不再需要重新计算,提升了拆分的性能,设计的还是非常巧妙的。

那么jdk1.8是如何做优化的呢?
假如原数组是16,现在扩容到32,那么原数组hash与增长出来的长度16做与运算,的出来的结果如果为0则下标不表,如果新位置就是原来的位置加16。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
HashMap扩容时,链表拆分是指将原来的链表根据元素的哈希值进行拆分,并重新分配到新的扩容后的数组中的位置上。 具体来说,当HashMap需要扩容时,它会创建一个新的更大的数组,并将原来的元素重新分配到新的数组中。在这个过程中,原来的链表会被拆分成两个链表:一个是哈希值与原数组容量按位与结果为零的元素组成的低位链表,另一个是哈希值与原数组容量按位与结果不为零的元素组成的高位链表拆分的过程是通过遍历原来的链表,判断每个元素的哈希值与原数组容量按位与的结果来进行的。如果结果为零,则将元素放入低位链表中;如果结果不为零,则将元素放入高位链表中。最后,在遍历完成后,将低位链表和高位链表分别放回新的数组中的对应位置。 总结起来,HashMap扩容时通过对元素的哈希值与原数组容量按位与的结果进行判断,将原来的链表拆分成低位链表和高位链表,并将它们分别放入新的数组中的合适位置。这样可以有效地避免在扩容后出现太多的冲突,提高HashMap的性能和效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JavaSourceCodeAnalysis:JDK二进制阅读笔记,包括Java常用集合类和Java常用和发工具(同步工具,线程安全...](https://download.csdn.net/download/weixin_42138525/16089759)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [jdk1.8HashMap扩容链表拆分过程解析](https://blog.csdn.net/leisure_life/article/details/123445508)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值