版权声明:本文为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解析相关推荐

  1. HashMap源码解析(JDK1.8)

    HashMap源码解析(JDK1.8) 目录 定义 构造函数 数据结构 存储实现源码分析 删除操作源码分析 hashMap遍历和异常解析 1. 定义 HashMap实现了Map接口,继承Abstrac ...

  2. 面试官系统精讲Java源码及大厂真题 - 08 HashMap 源码解析

    08 HashMap 源码解析 自信和希望是青年的特权. --大仲马 引导语 HashMap 源码很长,面试的问题也非常多,但这些面试问题,基本都是从源码中衍生出来的,所以我们只需要弄清楚其底层实现原 ...

  3. hashmap删除指定key_Java集合之HashMap源码解析(JDK8)

    哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景非常丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出 ...

  4. 通俗易懂Hashmap源码解析

    Hashmap源码解析 一.Hashmap数据结构 哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的值即 key,就可以找到其对应的值即 Value.哈希的思路很简单 ...

  5. Java集合框架之三:HashMap源码解析

    Java集合框架之三:HashMap源码解析 版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! HashMap在我们的工作中应用的非常广泛,在工作面试中也经常会被问到,对于这样一个重要的集 ...

  6. 史上最详细的HashMap红黑树解析

    HashMap红黑树解析 红黑树介绍 TreeNode结构 树化的过程 红黑树的左旋和右旋 TreeNode的左旋和右旋 红黑树的插入 TreeNode的插入 红黑树的删除 TreeNode的删除节点 ...

  7. 红黑树分析与JDK8中HashMap源码解析

    红黑树分析与JDK8中HashMap源码解析 BST O(1), O(n), O(logn), O(nlogn) 的区别 红黑树-RBTree 插入数据 HashMap中红黑树的插入操作 HashMa ...

  8. php的延迟绑定,PHP延迟静态绑定使用方法实例解析

    这篇文章主要介绍了PHP延迟静态绑定使用方法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 PHP的继承模型中有一个存在已久的问题,那就是在 ...

  9. Dom方法,解析XML文件

    Dom方法,解析XML文件的基本操作 1 package com.demo.xml.jaxp; 2 3 import java.io.IOException; 4 5 import javax.xml ...

最新文章

  1. java文件名与class关系
  2. html5 游戏前景怎么样,独家 HTML5游戏目前究竟怎么样?看完这篇文章,你或许会清晰很多...
  3. qt messagebox退出程序_[Qt] Mac平台安装最新版qt的方法(源码编译) - 刘傲天
  4. zabbix proxy mysql_zabbix proxy 配置
  5. Supervisor进程守护监控
  6. DPDK examples cmdline完全注释(添加quit功能)
  7. 51Nod-1062 序列中最大的数【序列计算+打表】
  8. python与office结合可以干什么-震惊!当Python遇到Excel后,将开启你的认知虫洞
  9. 维修技术论坛专用工具包 v5.0
  10. Amesim液压仿真基础与液压知识经验结合专题
  11. lbp2900打印机linux驱动下载,lbp2900打印机驱动下载
  12. 利用IV分析仪测量二极管的伏安特性的测量方法及步骤
  13. 信安冬令营实训报告(信息收集,主机渗透,内网渗透)
  14. push_back讲解
  15. 七绝高手都有哪些?中国历史上10大七言绝句诗人排行榜
  16. 诛仙3服务器查询系统,《诛仙3》4月1日服务器数据互通公告
  17. 黑客的滑铁卢——美国大断网全纪实
  18. 简单解释op(面向过程procedure- oriented)与oo(面向对象object-oriented)
  19. 阿里云网站备案申请被驳回的问题解答汇总
  20. 社团结构 matlab,社团结构

热门文章

  1. zookeeper的重连思考
  2. win电脑主板设置的Bios密码清除方法
  3. Kali linux最新2018年安装Netspeed
  4. vscode配置远程连接失败:过程试图写入的管道不存在(已解决)
  5. anylogic第三课—多层建筑行人疏散仿真讲解
  6. Unity手游制作记-制作通用镜头控制器
  7. 大学计算机基础:信息处理技术实验教程,大学计算机基础实验教程
  8. 四、降维——流形学习 (manifold learning)
  9. Windows API用以实现屏幕截图的方法
  10. 怎么用计算机表达爱意,简单表达爱意的句子