【小话HashMap系列 NO.2】冲突过后,探寻下标计算的秘密

本文接上篇【小话HashMap系列 NO.1】探寻那些不为人知的隐秘角落

我是小月,我本来在兵工厂的椅子上好好坐着,却来了一位女郎直接坐在了我腿上。

“你抢了我的位置… …”她这样说。

hash冲突

进入兵工厂时,工作人员给我们分发了一块电子显示屏,上面显示着我们的座位号,我的座位号是 ‘6’ 。

但她的显示屏上也写着 ‘6’,现在一个椅子分配给了两个参观者,这可怎么办?

在这里插入图片描述

”要不你先起来,我让你?“ 腿上坐着一位女郎,我极度不自在,还是把位置让给她坐好了。

“本来就是我的座位!”她横了我一眼,摇着脚尖,翘着的二郎腿没有放下去的意思。她赖在我腿上啦!不过她身上的味道闻起来真的好香呀。

这样下去也不是办法,毕竟我是一个血气方刚的‘男对象’!没办法,只好向旁边座位的老爷爷求助。

“Amia,你帮帮我。”

刚才还给我热心讲解兵工厂规则的老爷爷,转眼居然已经闭目养神起来,只是幽幽地说上了一句,“这位置,还真是这位小兄弟的。”

这说的叫什么话?这不是火上浇油吗!老爷爷真是的!

“不用不用,我让给你坐就是了。”我准备起身,偏偏女郎一只手在这时按在我肩上,不让我站起来。

“好好坐着,我们的位置你说了可不算,在工作人员过来之前,你最好老实坐着别乱动。”她轻哼了一声,“我不喜欢我的板凳晃来晃去!”

她说什么?她把我当她的板凳了!希望工作人员早点来吧,给别人当凳子真不是一件舒服的事,除非她温柔一点还差不多。

等了一小会儿,终于有工作人员注意到我们这边的异常,快步走了过来。

“你们的座位号冲突了?” 工作人员问。

“是。我们这种情况是采用头插法处理吧?偏偏旁边的老爷子有反对意见。”女郎很不满地说道。

“抱歉。”工作人员拿出《兵工厂说明手册》翻看后,说道:“您说的是1.7之前的版本了,如今我们是全新升级版1.8,所以这一块的规则有调整。现在我们采用尾插法处理座位号的冲突。”

“改了?”女郎晃动的鞋尖停止下来,顿了一秒才说道,”行吧,那你帮我搬一把椅子过来吧。“

工作人员转身搬椅子去了。

“对不起,是我弄错了。我向你道歉。”女郎站起来,冲我歉意一笑。

她突然温柔起来,让我有些不适应,连忙回道:“没关系”。

工作人员搬来椅子,她在我前面坐了下来,现在我们的座位是这样的。

在这里插入图片描述

呼,总算处理掉了大麻烦,不过她们说的头插法尾插法究竟是什么意思?我想着《兵工厂说明手册》应该会有答案。

“嘿嘿,小兄弟,你可错过了一段姻缘呐~” Amia不知道什么时候结束了闭目养神,小声地在我耳边说着。我转过头就看见了他纯洁的笑容。

呸,老不正经的!我在心里得出结论。不行,我得赶紧转移话题。

“她们说的头插法和尾插法是什么意思呢?”我问道,我可不想他再继续刚才的话题。

刚好我也翻到了手册上的说明:

哈希冲突:参观者座位号重复。

解决:数组+链表的方式处理。

特别说明:jdk1.7之前的版本,新增元素到链表中使用头插法;jdk1.8之后的版本,链表使用尾插法。

Amia挺直了后背,又恢复了一本正经的老爷爷模样,他解释说:“还记得我给你讲的,咱们座位的计算方式吧。调用我们自身的hashcode()方法获取一个int值,再将int值对数组长度进行取模运算。我写了两个例子,你看看。”

他递过来一张纸片,上面写着:

6%16 = 6;

22%16 = 6;

“看明白了吧,既然是取模运算,那我们的座位号肯定会冲突,这种情况也称作哈希冲突。

而解决的方案也就是采用数组+链表的方式处理咯。"

在这里插入图片描述
看完这些,我顿时明白了。Amia正经起来果然还是有货的嘛。

数组下标计算方式详解

“之前我只是给你讲了一个简易版本的下标计算,现在,我仔细给你讲解一下。”Amia问,”你知道位运算吗?“

我摇摇头。

“很简单,位运算就是将十进制转换成二进制来进行运算的方法,在我们的世界里,位运算是效率最高的一种运算方式。我简单给你介绍两种,然后你才能理解我们的座位号到底是怎么计算出来的。”

异或运算 ^
在这里插入图片描述
结果: 52 ^ 68 = 112

与运算&
在这里插入图片描述
结果 : 52 & 68 = 4

“现在你已经学会‘异或’运算和‘与’运算了,翻到《兵工厂说明手册》的附页,上面有座位号计算的详细公式。”
Amia示意我往后翻,我赶紧打开附页,找到了座位号计算公式:

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

“我用字符串 ‘I am the moon’ 来给你完整的解释一遍,认真看图。”Amia开始在纸上画起来。
在这里插入图片描述
"以上是调用hash()方法获取的结果,座位号(数组下标)的计算依赖上面的结果,具体的计算公式看这里。”Amia翻了一页,指给我看。

在这里插入图片描述

tab[i = (n - 1) & hash]

i :座位号

n: 数组长度

hash:调用hash()方法获取的结果值

他继续在纸上画着。
在这里插入图片描述
“现在明白了吧?” Amia长长呼出一口气,笑着问道。

“明白了。”不得不说,他讲解得很清楚,还补充了我不会的位运算方面的知识。

我本来以为,我已经知道了所有座位号的计算规则,毕竟这套规则已经非常复杂了。但Amia接下来的一句话,让我了解到事情没有这么简单。

Amia说:“如果是1.7之前的版本,讲解第一次的规则就够了。但是现在是1.8的新版,一切都大不同了。”

我脱口而出:“扩容时座位号的计算规则不同?”

Amia露出一个带有深意的笑容,“累了,喝口水。你要学的东西还多着呢,如果我没猜错的话,兵工厂就要拉响【贪吃蛇】警报了,等着看吧… …”

分隔线

贪吃蛇。【噗~】,你能猜到【贪吃蛇】警报是什么意思吗?下一篇揭晓。

To be continued… …

任何美好的事情都值得分享,关于生活,关于工作(认真工作可以让生活更美好)。如果喜欢我的文章,可以关注我的公众号【猿月亮】和我互动哦。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值