关于HashMap的table下标计算——tableSizeFor()方法解析
2017-10-25 00:00
477 查看
相关的代码片段如下:
代码段1:
代码段2:
主要解析代码片段1:
举个例子:n=13,其二进制编码为00001101,
n>>>1,前方补0,末位移除,最后得到00000110
2. | 和 |= 表示:逻辑或 和 或等于
举个例子:
逻辑或| 1001|0110 结果是 1111
或等于|= 先逻辑或,结果再赋值给前面的变量
n=5 (0101),
n |=3, 3(0011)
n=6, 6(0110)
为什么要对cap做减1操作?
这是为了防止,cap已经是2的幂。如果cap已经是2的幂, 又没有执行这个减1操作,则执行完后面的几条无符号右移操作之后,返回的capacity将是这个cap的2倍。
如果n这时为0了(经过了cap-1之后),则经过后面的几次无符号右移依然是0,最后返回的capacity是1(最后有个n+1的操作)。 以下只讨论n不等于0的情况。
由于n不等于0,则n的二进制表示中总会有一bit为1,这时考虑最高位的1。通过无符号右移1位,则将最高位的1右移了1位,再做或操作,使得n的二进制表示中与最高位的1紧邻的右边一位也为1,如000011xxxxxx。
这个n已经经过了
3ff0
p;操作。假设此时n为000011xxxxxx ,则n无符号右移两位,会将最高位两个连续的1右移两位,然后再与原来的n做或操作,这样n的二进制表示的高位中会有4个连续的1。如00001111xxxxxx 。
这次把已经有的高位中的连续的4个1,右移4位,再做或操作,这样n的二进制表示的高位中会有8个连续的1。如00001111 1111xxxxxx 。
所以取值到
看到这个地方,你应该基本明白了吧!
代码段1:
static final int MAXIMUM_CAPACITY = 1 << 30; /** * Returns a power of two size for the given target capacity. */ 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; }
代码段2:
public HashMap(int initialCapacity, float loadFactor) { /**省略此处代码**/ this.loadFactor = loadFactor; this.threshold = tableSizeFor(initialCapacity); }
主要解析代码片段1:
1、tableSizeFor()的功用
此方法用于找到大于等于initialCapacity的最小的2的幂(initialCapacity如果就是2的幂,则返回的还是这个数)2、算数逻辑符解析
1. >>> 表示:无符号右移举个例子:n=13,其二进制编码为00001101,
n>>>1,前方补0,末位移除,最后得到00000110
2. | 和 |= 表示:逻辑或 和 或等于
举个例子:
逻辑或| 1001|0110 结果是 1111
或等于|= 先逻辑或,结果再赋值给前面的变量
n=5 (0101),
n |=3, 3(0011)
n=6, 6(0110)
3、算法解析
int n = cap - 1;
为什么要对cap做减1操作?
这是为了防止,cap已经是2的幂。如果cap已经是2的幂, 又没有执行这个减1操作,则执行完后面的几条无符号右移操作之后,返回的capacity将是这个cap的2倍。
如果n这时为0了(经过了cap-1之后),则经过后面的几次无符号右移依然是0,最后返回的capacity是1(最后有个n+1的操作)。 以下只讨论n不等于0的情况。
第一次右移
n |= n >>> 1;
由于n不等于0,则n的二进制表示中总会有一bit为1,这时考虑最高位的1。通过无符号右移1位,则将最高位的1右移了1位,再做或操作,使得n的二进制表示中与最高位的1紧邻的右边一位也为1,如000011xxxxxx。
第二次右移
n |= n >>> 2;
这个n已经经过了
n |= n >>> 1;&nbs
3ff0
p;操作。假设此时n为000011xxxxxx ,则n无符号右移两位,会将最高位两个连续的1右移两位,然后再与原来的n做或操作,这样n的二进制表示的高位中会有4个连续的1。如00001111xxxxxx 。
第三次右移
n |= n >>> 4;
这次把已经有的高位中的连续的4个1,右移4位,再做或操作,这样n的二进制表示的高位中会有8个连续的1。如00001111 1111xxxxxx 。
以此类推
注意,容量最大也就是32bit的正数,因此最后n |= n >>> 16;,最多也就32个1。但是这时已经大于了
MAXIMUM_CAPACITY,因为:
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
所以取值到
MAXIMUM_CAPACITY。
实例如下:
看到这个地方,你应该基本明白了吧!
相关文章推荐
- JDK源码阅读之HashMap -- hash值计算方式、下标查找及tableSizeFor方法
- JDK1.8 HashMap中tableForSize()方法解析
- HashMap方法hash()、tableSizeFor()
- HashMap中的tableSizeFor()方法
- HashMap源码注解 之 静态工具方法hash()、tableSizeFor()(四)
- 关于ios7上无法计算UITextView的contentSize.height的解决方法
- 关于字符串计算size的方法比较
- jdk8 hashmap tableSizeFor
- 关于Activity与Fragment混用中对于startActivityForResult方法的解析
- tableSizeFor(int cap)方法详解
- Java中一些关于日期、日期格式、日期的解析和日期的计算
- XML for Analysis(XMLA)开发详解-(7)XMLA Execute方法解析及实例(完)
- sp_MSforeachtable使用方法
- [导入]XML for Analysis(XMLA)开发详解-(7)XMLA Execute方法解析及实例(完)
- sp_MSforeachtable使用方法
- 关于String类的split方法解析
- [导入]XML for Analysis(XMLA)开发详解-(6)XMLA Discover方法解析及实例
- 关于Function.prototype.bindAsEventListener方法的解析
- 关于Function.prototype.bindAsEventListener方法的解析
- 关于XML解析的几个实用方法