HashMap源码(一)
本文主要是从学习的角度看HashMap源码
HashMap的数据结构
- HashMap是一个数组+链表的结构(链表散列),每个节点在HashMap中以一个Node存在;

HashMap的初始化
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
// 这里的MAXIMUM_CAPACITY=1 << 30(问题一: 为什么是30?)
if (initialCapacity > MAXIMUM_CAPACITY)
// 如果传入初始值大于1<<30 则默认值为最大;
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
// 这里是根据传入的初始值算得 大于输入参数且最近的2的整数次幂的数
this.threshold = tableSizeFor(initialCapacity);
}
HashMap中初始化方法如上。
- initialCapacity参数为初始化大小的值,默认为16,问题二:这里为什么为16?;
- loadFactor参数我理解为扩容权重比,默认值为0.75,问题三:这里为什么是0.75?,就是当HashMap的容量达到HashMap的数组长度*loadFactor时就会进行扩容。也就是HashMap中的 resize 方法
初始化方法代码不多,此处为了效率运用了很多的位运算;
首先: 为什么HashMap的容量永远是2的整数倍?
- 首先我们可以看源码知道HashMap中元素的位置计算是 hash & (n- 1),为啥要这么算我也不知道,反正这样的算法下 如果hashmap的长度刚好是2的倍数那么元素的分布相对来说是比较均匀的。减少元素碰撞的几率; 具体详细的可以看下这篇博文
- 所以这也解释了问题二的初始值为16即2的四次方;至于为啥一定是16,我也不知道,可能我比较杠精;
- 更新(12-11 ): 此处为什么是16在关于这个默认容量的选择,JDK并没有给出官方解释,我也没有在网上找到关于这个任何有价值的资料。(如果哪位有相关的权威资料或者想法,可以留言交流)
- 更新(12-23):详见问题二
问题一:MAXIMUM_CAPACITY = 1 << 30
- 首先这个值符合上面的原则,即大小为2的整数倍;而1<<30这个值我们可以尝试发现:
System.out.println(1<<30); // 1073741824
System.out.println(1<<31); // -2147483648
System.out.println(1<<32); // 1
- 因为int类型是32位整型,1左移31位的为 16进制的0x80000000代表的是-2147483648, 所以最大值只能为1>>30;至于为什么初始值不用Integer.MAX_VALUE,其实在resize方法中有下面这段代码:
if (oldCap >= MAXIMUM_CAPACITY) {
//若数组长度大于1>>30,这里则扩容Integer.MAX_VALUE;
threshold = Integer.MAX_VALUE;
return oldTab;
}
问题二:initialCapacity初始值为16
因为在使用是2的幂的数字的时候,Length-1的值是所有二进制位全为1,这种情况下,index的结果等同于HashCode后几位的值。
只要输入的HashCode本身分布均匀,Hash算法的结果就是均匀的。
这是为了实现均匀分布。
问题三: loadFactor默认值0.75
JDK 1.7中:
As a general rule, the default load factor (.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the lookup cost (reflected in most of the operations of the HashMap class, including get and put). The expected number of entries in the map and its load factor should be taken into account when setting its initial capacity, so as to minimize the number of rehash operations. If the initial capacity is greater than the maximum number of entries divided by the load factor, no rehash operations will ever occur.
翻译过来就是:
作为一般规则,默认负载因子(0.75)在时间和空间成本上提供了很好的折衷。较高的值会降低空间开销,但提高查找成本(体现在大多数的HashMap类的操作,包括get和put)。设置初始大小时,应该考虑预计的entry数在map及其负载系数,并且尽量减少rehash操作的次数。如果初始容量大于最大条目数除以负载因子,rehash操作将不会发生。理想状态下,在随机哈希值的情况,对于loadfactor = 0.75 ,虽然由于粒度调整会产生较大的方差,桶中的Node的分布频率服从参数为0.5的泊松分布。
接下来我们会具体看下HashMap的resize方法
博文推荐:https://www.hollischuang.com/archives/4320 (掘金看见的,写的很好)
HashMap源码(一)的更多相关文章
- HashMap 源码解析
HashMap简介: HashMap在日常的开发中应用的非常之广泛,它是基于Hash表,实现了Map接口,以键值对(key-value)形式进行数据存储,HashMap在数据结构上使用的是数组+链表. ...
- HashMap源码分析
最近一直特别忙,好不容易闲下来了.准备把HashMap的知识总结一下,很久以前看过HashMap源码.一直想把集合类的知识都总结一下,加深自己的基础.我觉的java的集合类特别重要,能够深刻理解和应用 ...
- JAVA源码分析-HashMap源码分析(一)
一直以来,HashMap就是Java面试过程中的常客,不管是刚毕业的,还是工作了好多年的同学,在Java面试过程中,经常会被问到HashMap相关的一些问题,而且每次面试都被问到一些自己平时没有注意的 ...
- Java集合---HashMap源码剖析
一.HashMap概述二.HashMap的数据结构三.HashMap源码分析 1.关键属性 2.构造方法 3.存储数据 4.调整大小 5.数据读取 ...
- 【转】Java HashMap 源码解析(好文章)
.fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...
- 【JAVA集合】HashMap源码分析(转载)
原文出处:http://www.cnblogs.com/chenpi/p/5280304.html 以下内容基于jdk1.7.0_79源码: 什么是HashMap 基于哈希表的一个Map接口实现,存储 ...
- HashMap源码解读(转)
http://www.360doc.com/content/10/1214/22/573136_78188909.shtml 最近朋友推荐的一个很好的工作,又是面了2轮没通过,已经是好几次朋友内推没过 ...
- HashMap源码剖析
HashMap源码剖析 无论是在平时的练习还是项目当中,HashMap用的是非常的广,真可谓无处不在.平时用的时候只知道HashMap是用来存储键值对的,却不知道它的底层是如何实现的. 一.HashM ...
- Java中HashMap源码分析
一.HashMap概述 HashMap基于哈希表的Map接口的实现.此实现提供所有可选的映射操作,并允许使用null值和null键.(除了不同步和允许使用null之外,HashMap类与Hashtab ...
- 转:【Java集合源码剖析】HashMap源码剖析
转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 您好,我正在参加CSDN博文大赛,如果您喜欢我的文章,希望您能帮我投一票 ...
随机推荐
- CentOS7安装MySQL报错,解决Failed to start mysqld.service: Unit not found
当输入命令 ~]# systemctl start mysql.service 要启动MySQL数据库是却是这样的提示 Failed to start mysqld.service: Unit not ...
- 解决“此Flash Player与您的地区不相容”
1.进入C:\Windows\System32\drivers\etc目录,将hosts文件拷贝到桌面,然后用文本编辑器,比如记事本,打开,在最后一行添加: 127.0.0.1 geo2.adobe. ...
- 在简单的JDBC程序中使用ORM工具
本文来自[优锐课]——抽丝剥茧,细说架构那些事. ORM(对象关系映射)是用于数据库编程的出色工具.只需一点经验和Java注释的强大功能,我们就可以相对轻松地构建复杂的数据库系统并利用生产力.关系数据 ...
- C# WPF聊天界面(3/3)
微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. C# WPF聊天界面(3/3) 阅读导航 本文背景 代码实现 本文参考 1.本文背景 系列文章 ...
- 基于SSM开发大学食堂采购管理系统源码
开发环境: Windows操作系统开发工具: Eclipse+Jdk+Tomcat+MySQL数据库 次项目分为管理员和普通用户两种角色 运行效果图
- Vue(八)---组件(Component)
组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码. 注册一个全局组件语法格式如下: Vue.component(tagName, optio ...
- ROS之usb_cam
source devel/setup.*sh roslaunch usb_cam usb_cam-test.launch rqt_graph查看动态消息图 当我们把鼠标放在/usb_cam/image ...
- antd-design
1. 有mock 时候进度条展示不正常
- 吴裕雄--天生自然HADOOP操作实验学习笔记:hive安装
实验目的 了解hive的原理和安装方式 学习使用MySQL数据库 使用hive进行基本操作 实验原理 1.Hive Hive是一个数据仓库技术,包括解释器.编译器.优化器,一次将一个sql语句装化为m ...
- JavaScript-跨浏览器事件处理程序(EventUtil)
事件操作对象: var EventUtil= { //添加事件 addHandler: function (element, type, handler) { if (element.addEvent ...