最近面试被问到hashmap的实现,因为前段时间刚好看过源码,显得有点信心满满,但是一顿操作下来的结论是基础不够扎实。。。

好吧,因为我开始看hashmap是想了解这到底是一个什么样的机制,具体有啥作用,并没有过于细节去了解,所以问到细节的地方就难免漏洞百出,

回来之后,决定吧容器类的实现原理,去专研一下,目的是为了以后写代码自己可以去优化它

好了,不BB了,直接上代码,hashmap中有这么一段代码

  1. //容器最大容量
  2. static final int MAXIMUM_CAPACITY = 1 << 30;
  3.  
  4. /**
  5. *
  6. * @program: y2019.collection.MyHashMap
  7. * @description: 这个方法用于找到大于等于initialCapacity的最小的2的幂(initialCapacity如果就是2的幂,则返回的还是这个数)。
  8. * @auther: xiaof
  9. * 总结:
  10. * 1.说白了就是为了保证所有的位数(二进制)都是1,那么就可以保证这个数就是2的幂
  11. * 2.不断做无符号右移,是为了吧高位的数据拉下来做或操作,来保证对应的底位都是1
  12. * @date: 2019/6/25 10:25
  13. */
  14. public static final int tableSizeFor(int cap) {
  15. //这是为了防止,cap已经是2的幂。如果cap已经是2的幂
  16. int n = cap - 1;
  17. //第一次右移,由于n不等于0(如果为0,不管几次右移都是0,那么最后有个n+1的操作),则n的二进制表示中总会有一bit为1
  18. //这里无符号右移一位之后做或操作,那么会导致原来有1的地方紧接着也是1
  19. //比如00000011xxxxxxxx
  20. //还有一点无符号右移是为了避免前位补1,导致数据溢出,因为负数是以补码的形式存在的,那么就会再高位补1
  21. n |= n >>> 1;
  22. //第二次无符号右移,并做或操作
  23. //00000011xxxxxxxx=>0000001111xxxxxx 这个时候就是4个1
  24. n |= n >>> 2;
  25. n |= n >>> 4;
  26. n |= n >>> 8;
  27. //由于int最大也就是2的16次幂,所以到16停止
  28. n |= n >>> 16;
  29. return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
  30. }

我开始的不明白的地方是为什么要做4次右移???为什么要做无符号右移???

那么我手动时间一个low点的版本我们对比一下

  1. public static final int tableSizeFor2(int cap) {
  2. //这是为了防止,cap已经是2的幂。如果cap已经是2的幂
  3. int n = cap - 1;
  4. n |= n & 0xffff;
  5. return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
  6. }

原谅我的无知,我的第一反应就是这个,想都没想为什么不这样做。。。

结果发现相差甚远

第三行就是我这第二个方法得到的值,除了吧负数排除之外,没啥屌用,就是把原来的n去掉符号之后做了一次与运算

这个题的原理是获取到这个入参的位数,然后获取2的N次幂

  1. public static final int tableSizeFor3(int cap) {
  2. //这是为了防止,cap已经是2的幂。如果cap已经是2的幂
  3. int n = (cap - 1) & 0xffff;
  4. String hex = Integer.toBinaryString(n);
  5. return (cap <= 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : (int) Math.pow(2, hex.length());
  6. }

我们再这样处理

我们发现好像很接近了,我们发现n为1的时候,我们得到的长度是2,如果是以大于等于这个数的2的N次幂的话,我觉得我下面这个方法视乎更符合要求

接下来我们来试试性能?

当我们需要计算的数量达到1000000的时候,我们发现,这两个操作的性能相差有点大。。。

好吧,结论发现就是,jdk的源码不亏是经过千锤百炼的,一些看不懂的操作也许就是故意而为!!!

多关注这些看不懂的操作,学会了你也是大神!!!

参考文章:

https://blog.csdn.net/fan2012huan/article/details/51097331

【数据结构】29、hashmap=》tableSizeFor 中求大于等于当前数的最小2的幂的更多相关文章

  1. 分页过滤SQL求总条数SQL正则

    public static void main(String[] args) throws Exception { String queryForScanUsers_SQL = "selec ...

  2. hashMap tableSizeFor 实现原理

    基于jdk1.8 hashMap实现,要求容量大小是2的整次方,例如:2/4/8/16/32/64/128...,而不能是中间的某个值.这是为什么呢? map是数组+链表的数据结构,读写数据都需要首先 ...

  3. 数据结构解析-HashMap

    概要 HashMap在JDK1.8之前的实现方式 数组+链表,但是在JDK1.8后对HashMap进行了底层优化,改为了由 数组+链表+红黑树实现,主要的目的是提高查找效率. 如图所示: JDK版本 ...

  4. Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)

    剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...

  5. 为什么很多人坚信“富贵险中求”?

    之家哥 2017-11-15 09:12:31 微信QQ微博 下载APP 摘要 网贷之家小编根据舆情频道的相关数据,精心整理的关于<为什么很多人坚信"富贵险中求"?>的 ...

  6. 程序员必须知道的数据结构:HashMap 与 LinkedHashMap

    为什么要说 HashMap 与 LinkedHashMap?第一:这两种数据结构是 Java Coder 中经常使用的数据结构.第二:这两种结构是最合适的能说明链表与数组的结构关系.在开始之前首先必须 ...

  7. SQL SERVER中求上月、本月和下月的第一天和最后一天 DATEADD DATEDIFF

    SQL SERVER中求上月.本月和下月的第一天和最后一天   1.上月的第一天 SELECT CONVERT(CHAR(10),DATEADD(month,-1,DATEADD(dd,-DAY(GE ...

  8. 支付宝微信O2O大战,WiFi广告在夹缝中求生存

    支付宝微信O2O大战,WiFi广告在夹缝中求生存 来自工信部的数据显示,截至2013年底,中国智能手机的保有量已经达到5.8亿台.国内平均有46%的时间选择WiFi上网. 商用WiFi已经成为了移动互 ...

  9. MATLAB中求矩阵非零元的坐标

    MATLAB中求矩阵非零元的坐标: 方法1: index=find(a); [i,j]=ind2sub(size(a),index); disp([i,j]) 方法2: [i,j]=find(a> ...

随机推荐

  1. 陕西师范大学第七届程序设计竞赛网络同步赛 F WWX的礼物【数学/k进制下x^n的位数/log】

    链接:https://www.nowcoder.com/acm/contest/121/F来源:牛客网 题目描述 WWX的女朋友送给了他一个礼物,可是礼物却被一把K进制密码锁锁住了.在礼物盒上还有一张 ...

  2. java的IO,AIO简单对比

    以下内容转载lzzzl Channel 通道 Buffer 缓冲区 Selector 选择器 其中Channel对应以前的流,Buffer不是什么新东西,Selector是因为nio可以使用异步的非堵 ...

  3. Manacher【p4555】 [国家集训队]最长双回文串

    题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同). 输入长度为 n 的串 S ,求 S 的最长双回文子串 T ,即可 ...

  4. codevs——1230 元素查找

    时间限制: 1 s 空间限制: 128000 Ks 题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 给出n个正整数,然后有m个询问,每个询问一个整数 ...

  5. 分析dump

    一.使用jmap工具生成dump文件 二.MAT工具的下载和安装 三.使用MAT工具进行内存泄露分析  -- Step 1 :  ps –ef | grep <process> (whic ...

  6. 物理像素,ppi,逻辑分辨率和物理分辨率

    1 明确几个概念: 物理像素:屏幕物理像素 屏幕像素密度ppi:pixels per inch,屏幕上每英寸可以显示的像素点的数量,即屏幕像素密度.顺便一提,ppi就是dpi,只不过有文章里说苹果喜欢 ...

  7. 【bzoj2839】【集合计数】容斥原理+线性求阶乘逆元小技巧

    (上不了p站我要死了,侵权度娘背锅) Description 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得 它们的交集的元素个数为K,求取 ...

  8. Windows下SVN权限配置过程详解

    本节讲解一下Windows下SVN权限配置说明,针对的是一个目录下多库的情况,下面是具体的介绍,希望通过本文的学习,你能够对SVN权限配置问题有更加深刻的认识. 1.本文档适用于对Subvesion的 ...

  9. Java多线程设计模式(1)

    1 线程中的几个方法解释 Thread.sleep(long 毫秒) 在指定的时间内让当前线程休眠,将控制权交给其他线程,休眠的线程依旧拥有它所占用的锁, Thread.yield(); 暂停或者放弃 ...

  10. Hibernate中cascade和inverse的作用

    Inverse和cascade是Hibernate映射中最难掌握的两个属性.两者都在对象的关联操作中发挥作用.1.明确inverse和cascade的作用inverse 决定是否把对对象中集合的改动反 ...