jdk8中hash()方法的学习记录

引入

我们知道hash算法的目的在于,让我们存储的值更更更散散散列的存储数据;
那要分析这个hash算法那就离不开寻址算法了,hashmap怎么决定存储位置的?

寻址算法

在这里插入图片描述
这是hashmap的put方法,我们可以发现hashmap的寻址算法:

(length - 1) & hash //决定值的存储位置index

寻址算法为什么这样设计?

hashmap的length是2的n次幂
length可能的值:2/4/8/16…
因为有&运算,我们转换成二进制:
( 2-1) :0000 … 0001
( 4-1) :0000 … 0011
( 8-1) :0000 … 0111
(16-1):0000 … 1111

&运算的结果是都为1,结果才是1;
例子:hash & (16-1)
1010 1010 1001 1111 0000 0110 1100 0011
0000 0000 0000 0000 0000 0000 0000 1111
结果: 0000 … 0011
hash &(length -1)的结果就是只会保留(length - 1)的低位数据,而且是不会大于(length -1);
这样就有效的控制了寻址算法的值刚好在我们定义的length范围内。

这也是为什么hashmap保证length是2的n次幂的原因

hash算法

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

直接看hash()的源码

拿到hashcode了为什么还要右移16位?还做了一次^运算?

key==null

hashmap是可以存key=null;
从代码看key==null的时候默认决定了位置index=0

hashmap是数组+链表;值的注意的是,null只是存储在数组index为0的位置,而具体在链表的哪个位置是不确定的。

key!=null

hashcode:一个32位的int值

我们假想一种情况:
有没有可能我们存储的值的key的hashcode大部分都是1在高位
例如:
1011 0000 … 0000
1000 0000 … 0000
0011 0000 … 0000

寻址算法又是取得hash值的低位数据 ===》 这导致一个结果就是高位数据集中在index=0;
这应该不会有人觉得这结果符合散列的要求吧?

为什么要>>>16?寻址算法导致的结果是index位置是hash值的低位决定,那高位岂不是没了参与感?

那就让高位也有参与感:
1、把hashcode右移16位,这样高位的16位数据平移到了低位;
2、高16位平移后和低16位做一次运算,这不就都参与了?

解决了>>>问题,那为什么要用^,而不是&或者|?

&:都为1则为1 ==》 有0就为0,结果更偏向于0
|:有1则为1 ==》 结果更偏向于1
^:相同为0,不同为1 ==》 …

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值