hashMap tableSizeFor 实现原理
基于jdk1.8
hashMap实现,要求容量大小是2的整次方,例如:2/4/8/16/32/64/128...,而不能是中间的某个值。这是为什么呢?
map是数组+链表的数据结构,读写数据都需要首先获取数组中的下标值,获取的方式是通过hashcode取余。取余so easy,我们都会,假定运算后的hashcode=17,容量大小capacity=16,17%16=1,很容易得出元素落在数组的下标[1]内。
但是还有一种方式可以获取到正确的下标值,17 &(16-1)=1。
17二进制: 10001
15二进制: 01111
17&15: 00001 = 1
计算机的物理特性,决定位运算才是取余的正确打开方式。但是却有一个限制,被位与的数值有效位必须全部都是1,如15:1111可以,13:1101则不行。
这里位与运算得到的是下标位置,数组容量要在最大下标值的基础上加1,等价于二进制中被位与的数值进位,如15进1位=16:10000,2的4次方。
如果我们new HashMap<>(13),输入一个非整次方的数值,hashmap会自动调整成最近的整次方,例如这里的13最终会转换成16,实现方法为:java.util.HashMap#tableSizeFor
怎么实现呢?
2的整次方的特性是二进制有效位只有一个1,退位后当前1消失,后面bit位全补1,例如16:10000,退位后01111。13的二进制:1101,结构上看只要第二个bit补1(1101->1111),再进位(1111->10000)就可以了。1101->1111->
我们来分析实现
首先把方法复制出来,加上一些日志方便分析:
static final int MAXIMUM_CAPACITY = 1 << 30;
static final int tableSizeFor(int cap) {
System.out.println(Integer.toBinaryString(cap));
int n = cap - 1;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 1;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 2;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 4;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 8;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 16;
System.out.println(Integer.toBinaryString(n));
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
public static void main(String[] args) {
tableSizeFor(MAXIMUM_CAPACITY);
}
int n = cap - 1先退位,所以最终实现的结果是n的bit位全补1。
使用的最大容量+1,这样看日志比较清晰。
1000000000000000000000000000001
1000000000000000000000000000000
1100000000000000000000000000000
1111000000000000000000000000000
1111111100000000000000000000000
1111111111111111000000000000000
1111111111111111111111111111111
看到规律了吗?tableSizeFor首先获取最高位的1,二进制退位规则决定一定能够获取到最高位的1,然后进行不停的bit复制,1生2,2生4等等。int类型只有32位,所以复制到16位终止。
最后将n进位,即得到2的整次方,不过限定不能大于1>>30;
hashMap tableSizeFor 实现原理的更多相关文章
- Java中HashMap底层实现原理(JDK1.8)源码分析
这几天学习了HashMap的底层实现,但是发现好几个版本的,代码不一,而且看了Android包的HashMap和JDK中的HashMap的也不是一样,原来他们没有指定JDK版本,很多文章都是旧版本JD ...
- HashMap底层实现原理(JDK1.8)源码分析
ref:https://blog.csdn.net/tuke_tuke/article/details/51588156 http://www.cnblogs.com/xiaolovewei/p/79 ...
- 一文搞定HashMap的实现原理和面试
原文 https://juejin.im/post/5d09f2d56fb9a07ec7551fb0 HashMap在日常开发中基本是天天见的,而且都知道什么时候需要用HashMap,根据Key存取 ...
- HashMap的工作原理
HashMap的工作原理 HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道HashTable和HashMap之间 ...
- HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
①HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象.当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算h ...
- HashMap的工作原理深入再深入
前言 首先再次强调hashcode (==)和equals的真正含义(我记得以前有人会说,equals是判断对象内容,hashcode是判断是否相等之类): equals:是否同一个对象实例.注意,是 ...
- [转] HashMap的工作原理
HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此 ...
- 【转】HashMap的工作原理
很好的文章,推荐Java的一个好网站:ImportNew HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hasht ...
- 转:HashMap的工作原理,及笔记
HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此 ...
随机推荐
- Linux下进行程序设计时,关于库的使用:
一.gcc/g++命令中关于库的参数: -shared: 该选项指定生成动态连接库: -fPIC:表示编译为位置独立(地址无关)的代码,不用此选项的话,编译后的代码是位置相关的,所以动态载入时,是通过 ...
- tms web core 里面调用pascal 过程。
procedure show(s:string);begin showmessage(s);end; procedure TForm3.WebButton1Click(Sender: TObject ...
- jquery特殊字符转义方法
//特殊字符转义function escapeJquery(srcString) { // 转义之后的结果 var escapseResult = srcString; // javascript正则 ...
- BZOJ 4407 于神之怒加强版 (莫比乌斯反演 + 分块)
4407: 于神之怒加强版 Time Limit: 80 Sec Memory Limit: 512 MBSubmit: 1067 Solved: 494[Submit][Status][Disc ...
- DocumentFragment类型
nodeType 11 nodeName #document-fragment nodeValue NULL parentNode null createdocumentfragment()方法创建了 ...
- java高精度实数和小数
java 高精度实数和小数 String s = "1231222222222222222222222222222222222222222222222222222222"; Big ...
- 实现1sym转换成2个sym送给CVI(VGA数据)
CVI的时序如下 :de指示数据有效. 从下面的程序看,同步码的长度不会影响对有效数据的判断.同步码的作用更多的是用于计算行及一行的像素数目.方案一: 1 module vga_1sym_2_2sym ...
- SQL编写-谁和谁是好朋友
problem: 用户表 姓名 张三 李四 王五 好友表 姓名 好友姓名 张三 李四 张三 王五 李四 张三 用户表里面姓名必须在好友表里面互加为好友,请问如何找出还没有加为好友的姓名 ...
- Linux服务器密钥安全登录
使用密钥登录的好处:1.省事,不用每次去敲用户名和密码:2.安全,密钥长度一般是1024位,比我们设的密码要长得多: 以下是为新用户jackson添加密钥登录的步骤. 1.添加用户,并添加到sudoe ...
- Silverlight4.0正式版(Silverlight4_Tools)离线安装
1.从微软的网站下载Silverlight4_Tools.exe(或者http://download.csdn.net/detail/taomanman/4522848)2.执行Silverlight ...