基于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 实现原理的更多相关文章

  1. Java中HashMap底层实现原理(JDK1.8)源码分析

    这几天学习了HashMap的底层实现,但是发现好几个版本的,代码不一,而且看了Android包的HashMap和JDK中的HashMap的也不是一样,原来他们没有指定JDK版本,很多文章都是旧版本JD ...

  2. HashMap底层实现原理(JDK1.8)源码分析

    ref:https://blog.csdn.net/tuke_tuke/article/details/51588156 http://www.cnblogs.com/xiaolovewei/p/79 ...

  3. 一文搞定HashMap的实现原理和面试

    原文  https://juejin.im/post/5d09f2d56fb9a07ec7551fb0 HashMap在日常开发中基本是天天见的,而且都知道什么时候需要用HashMap,根据Key存取 ...

  4. HashMap的工作原理

    HashMap的工作原理   HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道HashTable和HashMap之间 ...

  5. HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别

    ①HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象.当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算h ...

  6. HashMap的工作原理深入再深入

    前言 首先再次强调hashcode (==)和equals的真正含义(我记得以前有人会说,equals是判断对象内容,hashcode是判断是否相等之类): equals:是否同一个对象实例.注意,是 ...

  7. [转] HashMap的工作原理

    HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此 ...

  8. 【转】HashMap的工作原理

    很好的文章,推荐Java的一个好网站:ImportNew HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hasht ...

  9. 转:HashMap的工作原理,及笔记

    HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此 ...

随机推荐

  1. ServiceDesk Plus 服务管理自动指派工单功能

  2. OpenCV-图像通道转换问题

    OpenCV-MAT对象中使用plt.imshow(img[:,:,::-1])如何实现将第二轴反向? 系统平台:win10 x64 一.明确几个概念: 1.OpenCV内部每个通道并没有固定对应某种 ...

  3. 【转】python 修改os环境变量

    举一个很简单的例子,如果你发现一个包或者模块,明明是有的,但是会发生这样的错误: >>> from algorithm import *Traceback (most recent ...

  4. Python开课复习7

    操作系统 操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来. #1. 打开文 ...

  5. mybatis拦截器案例之获取结果集总条数

    最近做的项目前端是外包出去的,所以在做查询分页的时候比较麻烦 我们需要先吧结果集的条数返回给前端,然后由前端根据页面情况(当前页码,每页显示条数)将所需参数传到后端. 由于在项目搭建的时候,是没有考虑 ...

  6. myeclipse cannot connect to vm

    启动tomcat时,tomcat可以直接运行,而debug时弹出 解决方法:打开360安全卫士的功能大全找到修复网络(LSP)点击立即修复就可以使用debug

  7. highChart图表

    Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习.个人网站和非商业用途使用.HighCh ...

  8. VirtualBox安装增强工具时:Unable to install guest additions: unknown filesystem type 'iso9660'

    解决方法: sudo apt-get install --reinstall linux-image-$(uname -r) 参考:http://askubuntu.com/questions/596 ...

  9. 发布自己的第一版asp.net core的RESTful接口程序

    使用window开发一个简单的asp.net Core的RESTfull程序,网上很多,这里不说,我是直接使用IDE自己生成的项目来发布的.没有修改过主要代码.在IDE里发布到本地目录,得到类似文件 ...

  10. What's New In Python 3.X

    As Python updating to python 3.6, its performance is better than Python 2.x, which is good news to e ...