java - HashMap.tableSizeFor(...)。这段代码如何四舍五入到 2 的下一个幂?
问题描述
请描述一下这n| = n >>> x
5 行的作用?
我对操作员的工作不|
感兴趣>>>
。我对数学语言中复杂逻辑的作用很感兴趣。
/**
* 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 的所有(正)幂都恰好设置了 1 位;和(2 - 1 的幂)的所有位都设置为小于最高有效位。所以,我们可以找到下一个最大的二的幂
- 减 1
- 设置所有低有效位
- 加1回
这些位移操作通过“涂抹”设置的位来实现该过程的第二步。
所以:
n |= n >>> 1;
会做类似的事情:
01010000
| 00101000
= 01111000
如果你再次这样做,你会再次“涂抹”数字(仍然只移动 1):
01111000
| 00111100
= 01111100
继续这样做,你最终会得到一个设置了所有次要位的数字:
01111111
在最坏的情况下,当最高有效位是第 31 位时,您必须这样做 30 次(对于正的有符号 32 位整数):
01xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
=> 011xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
=> 0111xxxxxxxxxxxxxxxxxxxxxxxxxxxx
=> 01111xxxxxxxxxxxxxxxxxxxxxxxxxxx
=> 011111xxxxxxxxxxxxxxxxxxxxxxxxxx
...
=> 01111111111111111111111111111111
(x
只是意味着它可能是零或一)
但是您可能会注意到一些有趣的事情:在第一次拖尾之后,当移位 1 时,我们设置了两个最高有效位。因此,我们可以通过移动 2 来跳过操作,而不是移动 1:
01xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
=> 011xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
=> 01111xxxxxxxxxxxxxxxxxxxxxxxxxxx
继续这种模式,接下来移动 4:
=> 011111111xxxxxxxxxxxxxxxxxxxxxxx
移位 8:
=> 01111111111111111xxxxxxxxxxxxxxx
移动 16:
=> 01111111111111111111111111111111
因此,我们没有采用 30 次操作来设置所有较低有效位,而是采用了 5 次。
推荐阅读
- go - 第一次 golang 测试运行很慢
- visual-studio-code - Arraylist 无法解析为类型
- node.js - 如何使用 Promise 更新节点 js 中的变量?
- c++ - 链接头文件c ++时对函数的未定义引用
- python - 有没有可以运行python文件并显示unicode的程序?
- reactjs - React Native - 使用来自非组件函数的上下文
- excel - 除非应用程序关闭,否则链接文件不会关闭
- express - 如何使用 express.js 从 pug 中的文本输入中获取值?
- javascript - userinfo 命令在游戏活动中遇到问题
- java - 一个类中的main方法不能使用同一个项目Java中的任何对象