我叫小月,我参观了兵工厂 – HashMap,对兵工厂内部的规则有了许多的了解。还认识一位和善的老爷爷Amia,他教会了我特别多的东西。
本文承接
【小话HashMap系列 NO.1】探寻哪些不为人知的隐秘角落 NO.1
【小话HashMap系列 NO.2】冲突过后,探寻下标计算的秘密
扩容后下标重新计算
“好啦,现在我给你讲讲扩容之后,我们座位号的计算规则吧。” Amia休息好了,看上去精神百倍。
我已经迫不及待的想要知道了,他休息的时候,广播里已经又通知了好几次“扩容”了。
“快快快,赶快开始吧。”我把一张画纸放到Amia面前,他要是不画图给我,我根本不能明白他讲的内容。
“看好啦。当执行扩容后,数组长度-1,转换后的二进制就多了一位。而这一位参与运算的结果,直接决定了我们座位号的变化。”
Amia画了一张简单的示意图,我立刻就明白了他的意思。
“座位号计算规则还记得吗?” Amia问。
我点点头,翻开《兵工厂说明手册》,上面的公式已经被我提炼成了更加容易理解的样子。
下标值 =(数组长度-1)& hash()
“多出来的这一位,参与运算的结果,如果是0,那么我们的座位号就不会发生变化。如果结果是1,那么座位号=现在的位置+扩容前座位的数量(扩容前的数组长度)。”
什么意思?我又蒙圈了。
还好Amia一边画图,一边向我解释:“我还是用字符串 ‘I am the moon’ 举例,之前我们已经得到hash()后的结果是:770472065 “
“图中的计算结果,标成黑色并且添加下划线的,如果是0,则座位号不变。所以最后的座位号(数组下标值)仍然是1。”Amia说完,继续动手画着。
“我再给你举一个反面的栗子,方便你理解。”
“我明白了,每一次执行扩容后,数组长度变为原来的2倍,所以数组长度转换为二进制后比原来多了一位。多出来的这一位和hash()后的值计算的结果,就决定了我们的座位号变化还是不变。” 我恍然大悟。
Amia满意的点头,“看上去你已经完全明白了。”
我刚刚松了口气,还来不及享受掌握新知识的喜悦,就感觉到地面强烈震动起来,一阵整齐的脚步声传入耳中。
树形化
“怎么了?”我看见一队红衣服和黑衣服的警卫从入口跑进来,每个人都背着一把红黑相间的椅子。
Amia倒是见怪不怪地说道:“看吧,贪吃蛇警报响了。”
“贪吃蛇警报?”我不明所以。
“嗯。”Amia随手画了张图递给我,“你看看,这像不像贪吃蛇?”
“噗。” 你别说,我们的座位排列,在某种情况下还真的像是贪吃蛇。
“所以吧,兵工厂的领导发话了,这次说什么都要改变这种贪吃蛇的座位模式。”
我:“。。。”
Amia笑着道:“开个玩笑。贪吃蛇是我们瞎编的。”
“其实在兵工厂内部有一个秘密计算系统,可以直接定位到某位参观者的具体位置。以往座位编排采用 ‘ 数组+链表 ’的方式,在某些情况下查找效率极低,采用 ‘ 红黑树 ’ 的结构,可以提高查找和定位的效率。”
“什么时候会发生这样的转换呢?”
“当数组的长度大于64,并且链表的长度大于8的时候,链表就会转换成红黑树,这种变化被我们称作树形化。”
这时我想到一个问题:既然链表能转换成红黑树,那么在链表长度小于8 的时候,数据结构还会转换回去吗?
"这个问题我倒是没有想过。"Amia回答道,“不过《兵工厂说明手册》上肯定有说明,我们查一查。”
不一会儿,我就找到了答案。
反树形化:当 ‘红黑树’的节点个数 小于6时,红黑树会转换回链表。
“谢谢你,Amia。"我发自内心的感谢他,要不然我肯定会在迷惑中结束这次参观。
最后,终于大喇叭里响起了我期待已久的声音。
“各位久等了,这次我们兵工厂组织的汇报表演即将在5分钟后开始,感谢各位的光临… …”