HashMap方法tableSizeFor解析
版权声明:本文为CSDN博主「塔奇库玛」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35296366/article/details/125792358
tableSizeFor解析
这是HashMap源码中的一个方法,这个方法的作用是找到一个离cap最近的2的n次方数
例:cap = 14,return 16;cap = 76,return 128;
static final int tableSizeFor(int cap) {//-1可以保证当传入的数刚好是2的次方时,可以正确的返回其本身,例:传入的是16,经过下面的计算后还是返回16int 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;
}
先解释一下|=、>>>这两个运算符。
- 运算符|=
n |= n 等同于 n = n | n;
| 是位运算符(或) - 运算符>>>
符号>>> 是无符号右移运算符
就是把一个二进制数右移指定位数,正数高位补0,负数高位补1;
例:
int num = ; //00000000 00000000 00000000 10111101
//无符号右移1位
num = num>>> = 1;//00000000 00000000 00000000 01011110
//把上一步得到的num再做无符号右移2位运算得到
num = num>>> = 2;//00000000 00000000 00000000 00010111
了解了以上两个运算符的作用,应该就能初步看明白源码中的tableSizeFor方法了吧。但是大部分人第一次看的时候应该都是一脸懵逼的,颇有一种我明明都看明白了每步做了什么,为什么合起来就看不懂了的感觉。下面来解释一下。
先思考一个问题:
如果给我们一个二进制数cap = 00000000 00000000 00000000 10111101这个二进制数的最近的一个2的n次方数是多少呢?学过二进制,我们可以应该可以一眼看出来这个数是cap = 00000000 00000000 00000001 00000000
我们一眼看出来了,但是程序不行,所以要思考一种办法能通过代码找到这个数。
假设我们可以把最高位1以及其后面的位都置为1,然后加1是不是就能实现这个功能了,即:
步骤1、cap = 00000000 00000000 00000000 11111111
步骤2、cap = cap + 1 = 00000000 00000000 00000001 00000000
tableSizeFor就是通过这两个步骤实现的
static final int tableSizeFor(int cap) {//-1可以保证当传入的数是2的次方时,可以正确的返回其本身,例:传入的是16,经过下面的计算后还是返回16//步骤一int n = cap - 1;n |= n >>> 1;n |= n >>> 2;n |= n >>> 4;n |= n >>> 8;n |= n >>> 16;//步骤二n+1return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;}
这个代码的作用就是把最高位的1后面的所有位都置为1,而且从始至终其实只用到了最高位1这1位数字参与运算,非常的巧妙,膜拜。下面由一个例子来解释一下:
有个int数n,二进制为
n = 00000000 00000001 10111010 000001101;
现在我们只看最高位的1,1后面的位数用x代替,它是0还是1都不重要(后面你会发现确实不重要),表示为:
n = 00000000 00000001 xxxxxxx xxxxxxxx;把n做无符号右移1位运算并将结果赋值给m:
m = 00000000 00000000 1xxxxxxx xxxxxxxx;
把n与m做或运算,并将结果赋值给n,得到:
n = 00000000 00000001 1xxxxxxx xxxxxxxx;把n做无符号右移2位运算并将结果赋值给m:
m = 00000000 00000000 011xxxxx xxxxxxxx;
把n与m做或运算,并将结果赋值给n,得到:
n = 00000000 00000001 111xxxxx xxxxxxxx;把n做无符号右移4位运算并将结果赋值给m:
m = 00000000 00000000 0001111x xxxxxxxx;
把n与m做或运算,并将结果赋值给n,得到:
n = 00000000 00000001 1111111x xxxxxxxx;把n做无符号右移8位运算并将结果赋值给m:
m = 00000000 00000000 00000001 1111111x ;
把n与m做或运算,并将结果赋值给n,得到:
n = 00000000 00000001 11111111 1111111x ;把n做无符号右移16位运算并将结果赋值给m:
m = 00000000 00000000 00000000 00000001 ;
把n与m做或运算,并将结果赋值给n,得到:
n = 00000000 00000001 11111111 11111111 ;有没有发现到不知不觉就把最高位1后面的位数全部都变成1了,而且从始至终其实只有最高位的1以及通过这个1计算得到的数参与了运算,
前面被我们表示为x的位根本没有用到。
因为java中int类型是32位的,所以5次无符号右移刚好能覆盖到32位数。同理如果是8位数只需要位移到4,如果是16位数只需要位移到8,,64位数则需要位移到32。n |= n >>> 1;//到这一步最多可以得到2位1n |= n >>> 2;//到这一步最多可以得到4位1n |= n >>> 4;//到这一步最多可以得到8位1n |= n >>> 8;//到这一步最多可以得到16位1n |= n >>> 16;//到这一步最多可以得到32位1
把得到的n加1就能得到了一个最近的大于n的2的次方数。
HashMap方法tableSizeFor解析相关推荐
- HashMap源码解析(JDK1.8)
HashMap源码解析(JDK1.8) 目录 定义 构造函数 数据结构 存储实现源码分析 删除操作源码分析 hashMap遍历和异常解析 1. 定义 HashMap实现了Map接口,继承Abstrac ...
- 面试官系统精讲Java源码及大厂真题 - 08 HashMap 源码解析
08 HashMap 源码解析 自信和希望是青年的特权. --大仲马 引导语 HashMap 源码很长,面试的问题也非常多,但这些面试问题,基本都是从源码中衍生出来的,所以我们只需要弄清楚其底层实现原 ...
- hashmap删除指定key_Java集合之HashMap源码解析(JDK8)
哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景非常丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出 ...
- 通俗易懂Hashmap源码解析
Hashmap源码解析 一.Hashmap数据结构 哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的值即 key,就可以找到其对应的值即 Value.哈希的思路很简单 ...
- Java集合框架之三:HashMap源码解析
Java集合框架之三:HashMap源码解析 版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! HashMap在我们的工作中应用的非常广泛,在工作面试中也经常会被问到,对于这样一个重要的集 ...
- 史上最详细的HashMap红黑树解析
HashMap红黑树解析 红黑树介绍 TreeNode结构 树化的过程 红黑树的左旋和右旋 TreeNode的左旋和右旋 红黑树的插入 TreeNode的插入 红黑树的删除 TreeNode的删除节点 ...
- 红黑树分析与JDK8中HashMap源码解析
红黑树分析与JDK8中HashMap源码解析 BST O(1), O(n), O(logn), O(nlogn) 的区别 红黑树-RBTree 插入数据 HashMap中红黑树的插入操作 HashMa ...
- php的延迟绑定,PHP延迟静态绑定使用方法实例解析
这篇文章主要介绍了PHP延迟静态绑定使用方法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 PHP的继承模型中有一个存在已久的问题,那就是在 ...
- Dom方法,解析XML文件
Dom方法,解析XML文件的基本操作 1 package com.demo.xml.jaxp; 2 3 import java.io.IOException; 4 5 import javax.xml ...
最新文章
- java文件名与class关系
- html5 游戏前景怎么样,独家 HTML5游戏目前究竟怎么样?看完这篇文章,你或许会清晰很多...
- qt messagebox退出程序_[Qt] Mac平台安装最新版qt的方法(源码编译) - 刘傲天
- zabbix proxy mysql_zabbix proxy 配置
- Supervisor进程守护监控
- DPDK examples cmdline完全注释(添加quit功能)
- 51Nod-1062 序列中最大的数【序列计算+打表】
- python与office结合可以干什么-震惊!当Python遇到Excel后,将开启你的认知虫洞
- 维修技术论坛专用工具包 v5.0
- Amesim液压仿真基础与液压知识经验结合专题
- lbp2900打印机linux驱动下载,lbp2900打印机驱动下载
- 利用IV分析仪测量二极管的伏安特性的测量方法及步骤
- 信安冬令营实训报告(信息收集,主机渗透,内网渗透)
- push_back讲解
- 七绝高手都有哪些?中国历史上10大七言绝句诗人排行榜
- 诛仙3服务器查询系统,《诛仙3》4月1日服务器数据互通公告
- 黑客的滑铁卢——美国大断网全纪实
- 简单解释op(面向过程procedure- oriented)与oo(面向对象object-oriented)
- 阿里云网站备案申请被驳回的问题解答汇总
- 社团结构 matlab,社团结构