HashMap容量背后的原因

现象

在HashMap源码中,Size字段是这么存储的:
在这里插入图片描述

一个很有意思的现象是,为什么这里16不是直接用的16,而是1 << 4
在StatckOverFlow 中有这么一篇回答,可以深刻阐述背后的原因。总结一句话就是计算机是二进制的世界
原文地址:Why use 1<<4 instead of 16?

先说上面为什么用 1<<4,这里这么写,并不会改变背后的影响,这么写的一个原因是告诉开发者,容量必须是2的倍数。同时暗示开发者,容量在存储为二进制时,永远只有一位是1。比如上面的0001 0000。所以源码中描述最大容量用的也是 1 << 30。显然,用移位的表示方法更具可读性。
在这里插入图片描述

为什么必须是2的倍数?

在进行Hash运算的时候,Java底层是取余运算,比如,如果容量是100,那么Hash值为5、105、205的键值对都将存储在index为5的地方。这里的思想就像钟表一样是个环形的。

这里就涉及到了取余,想象一下,如果容量随意,比如1234,那么当Hash值是123456的时候,我们将进行,123455 % 1234的运算,让计算机计算看上去还行。

但如果我们不随意指定容量,而是指定容量必须是10的倍数,将会发生什么呢?比如容量是100,那么当Hash值是123456的时候,我们一眼就能看出 123456 % 100 = 56,所以应该存储在index是56的地方。

Amazing啊。

那对于计算机,有没有一眼就能求出来的设计方案呢?答案是容量指定为2的倍数,比如上图中,默认初始容量是16,那么底层存储的二进制码将是 10000,我们随机取一个Hash值用二进制表示,比如10111010110,那么怎么求得 10111010110 % 10000的结果呢?答案是 (10000 - 1) & 10111010110 = 0110。Amazing啊!!!一下就求出来了。

虽然现在计算机的运算能力很强,但是形如上面的123456 % 100 = 56的运算速度依然要比形如(10000 - 1) & 10111010110 = 0110的位运算速度小很多,在操作量比较大的情况下,采用后者的设计将带来非常可观的性能提升!!!甚至超过50倍!!!!!

在回到前面提到的计算机是二进制的世界,试想一下,如果计算机是基于三进制的,那可能HashMap的容量要求可能就不是2的倍数,而是三的倍数了。:)

共勉

所有你不能理解的计算机现象,都能从下一层设计中找到答案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值