基于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->

我们来分析实现

首先把方法复制出来,加上一些日志方便分析:

  1. static final int MAXIMUM_CAPACITY = 1 << 30;
  2.  
  3. static final int tableSizeFor(int cap) {
  4. System.out.println(Integer.toBinaryString(cap));
  5. int n = cap - 1;
  6. System.out.println(Integer.toBinaryString(n));
  7. n |= n >>> 1;
  8. System.out.println(Integer.toBinaryString(n));
  9. n |= n >>> 2;
  10. System.out.println(Integer.toBinaryString(n));
  11. n |= n >>> 4;
  12. System.out.println(Integer.toBinaryString(n));
  13. n |= n >>> 8;
  14. System.out.println(Integer.toBinaryString(n));
  15. n |= n >>> 16;
  16. System.out.println(Integer.toBinaryString(n));
  17. return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
  18. }
  19.  
  20. public static void main(String[] args) {
  21. tableSizeFor(MAXIMUM_CAPACITY);
  22. }
  1. int n = cap - 1先退位,所以最终实现的结果是nbit位全补1

使用的最大容量+1,这样看日志比较清晰。

  1. 1000000000000000000000000000001
  2. 1000000000000000000000000000000
  3. 1100000000000000000000000000000
  4. 1111000000000000000000000000000
  5. 1111111100000000000000000000000
  6. 1111111111111111000000000000000
  7. 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. CMDB 配置管理数据库

  2. GUI的最终选择Tkinter模块初级篇

    一.Tkinter模块的基本使用 1)实例化窗口程序 import tkinter as tk app = tk.Tk() app.title("FishC Demo") app. ...

  3. 爬虫模块之requests模块

    一 模块的下载安装 pip install requests 二 爬虫的介绍 什么是爬虫:就是模拟浏览器发送请求:保存到本地:提取有用的数据:保存到数据库 爬虫的价值:获取有用的数据,保存到数据库 爬 ...

  4. Spring mvc项目,使用jetty插件和tomcat路径相差一个项目名

    pom.xml: jetty 插件配置: <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId& ...

  5. C++之基于排序方法求一组数的中位数

    中位数也就是中值: 故需要先对数组进行排序(选择,插入,冒泡排序),然后在找出数组的中值. //求中值 #include<iostream> using namespace std; in ...

  6. 点击文字弹出一个DIV层窗口代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  7. 使用函数的列 group by 分组需要别名

    问题描述 使用如下截图的SQL统计数据,报1105错误,提示all columns in group by clause should be in the selected column. 给格式化 ...

  8. tokudb_tmp_dir导致的tokudb加载失败

    安装TOKUDB数据库,安装完成后为了使配置生效,重启完数据库后,发现: mysql> show engines; +--------------------+---------+ | Engi ...

  9. 1033 To Fill or Not to Fill

    PAT A 1033 To Fill or Not to Fill With highways available, driving a car from Hangzhou to any other ...

  10. python基于pillow库的简单图像处理

    from PIL import Image from PIL import ImageFilter from PIL import ImageEnhance import matplotlib.pyp ...