HashMap的源码浅析
一、HashMap 的数据结构
Java7 及之前主要是“数组+链表”,到了 Java8 之后,就变成了“数组+链表+红黑树”。
二、Java7 源码浅析:
在Java7 中,HashMap 是数据结构里学的 HashTable 经典的实现!
注意点:Java7 中的 HashMap 当我们new出来的时候,他就给我们初始化了底层的 Entry 数组!
1、HashMap()

它自行调用了一个有参的构造器,并传入了默认的数组长度和负载因子:


2、put()
大致流程:先根据 key 的哈希值获取数组索引,然后挨个在数组上查找是否有Entry key 哈希值和值都和 put 的 key 相同,有的话就覆盖 value 了;没有的话,才进行 Entry 的添加!


3、indexFor()
在这里获取数组索引,哈希值 &(数组长度-1),这也就是为什么数组长度为 2 的幂的原因!

4、addEntry()
在添加节点的时候,会进行是否扩容的判断!

三、Java7 中的问题:
- 死锁:头插法。因为复制的时候,依次把链表元素复制到新的数组中去,有可能部分元素获取的数组索引还是相同的,因为头插法会导致链表导致,从而形成环形链表,当CPU下次进入这个链表查询时,产生死锁!
- 安全隐患:Apache Tomcat 底层是使用哈希表来进行存储 Http request 的 parameters,如果此时http请求中的参数中有大量 hash 相同的 key,那么可能导致服务器中形成大量的环形链表,消耗大量CPU,发生Dos!2011年的时候 Tomcat 察觉到并临时想到了一个方法,提供了一个参数,用于限制参数的个数,默认值是 1W!而 Java8 在2014年的时候发布的时候,
四、Java8 的源码浅析:
HashMap()


put()
注意:此时,分配数组索引已经是在判断的时候做的了!

Java 8 相对于 7 的变化:
- new HashMap() 时,底层没有第一时间创建 默认长度的数组!
- 底层是 Node 数组,而非 Entry 数组
- 首次调用 put 方法的时候,才进行数组的创建!(延时加载)
- put 时,如果添加新节点的话,采用的是尾插法!(可避免 7 的死锁问题!)
- 7 的底层结构只有 数组+链表,8 则是 数组+链表+红黑树(当 put 的链表长度等于8,且数组长度等于 64 的时候,这个链表就会转为红黑树结构!)!
HashMap的源码浅析的更多相关文章
- HashSet其实就那么一回事儿之源码浅析
上篇文章<HashMap其实就那么一回事儿之源码浅析>介绍了hashMap, 本次将带大家看看HashSet, HashSet其实就是基于HashMap实现, 因此,熟悉了HashMap ...
- java并发:jdk1.8中ConcurrentHashMap源码浅析
ConcurrentHashMap是线程安全的.可以在多线程中对ConcurrentHashMap进行操作. 在jdk1.7中,使用的是锁分段技术Segment.数据结构是数组+链表. 对比jdk1. ...
- 【深入浅出jQuery】源码浅析--整体架构
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 【深入浅出jQuery】源码浅析2--奇技淫巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- Struts2源码浅析-ConfigurationProvider
ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...
- (转)【深入浅出jQuery】源码浅析2--奇技淫巧
[深入浅出jQuery]源码浅析2--奇技淫巧 http://www.cnblogs.com/coco1s/p/5303041.html
- Android 手势识别类 ( 三 ) GestureDetector 源码浅析
前言:上 篇介绍了提供手势绘制的视图平台GestureOverlayView,但是在视图平台上绘制出的手势,是需要存储以及在必要的利用时加载取出手势.所 以,用户绘制出的一个完整的手势是需要一定的代码 ...
- Android开发之Theme、Style探索及源码浅析
1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...
- 【深入浅出jQuery】源码浅析2--使用技巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
随机推荐
- 在java中构建高效的结果缓存
文章目录 使用HashMap 使用ConcurrentHashMap FutureTask 在java中构建高效的结果缓存 缓存是现代应用服务器中非常常用的组件.除了第三方缓存以外,我们通常也需要在j ...
- Cacti nagios zabbix 的区别
Cacti nagios zabbix 的区别 首先 Cacti 是一个用 rrdtool 来画图的网络监控系统, 通常一说到网络管理, 大家首先想到的经常是 mrtg, 但是 mrtg 画的图比较简 ...
- 【抓包工具】tcpdump
tcpdump - dump traffic on a network 根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析.它支 ...
- 【Linux常见命令】date命令
Linux date命令:可以用来显示或设定系统的日期与时间. 在显示方面,使用者可以设定欲显示的格式,格式设定为一个加号后接数个标记,其中可用的标记列表如下: 时间方面: %H : 小时(00..2 ...
- SpringBoot内置生命周期事件详解 SpringBoot源码(十)
SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringBoot事件监听 ...
- USACO Training Section 1.2 [USACO1.2]回文平方数
题目描述 回文数是指从左向右念和从右向左念都一样的数.如12321就是一个典型的回文数. 给定一个进制B(2<=B<=20,由十进制表示),输出所有的大于等于1小于等于300(十进制下)且 ...
- qt creator源码全方面分析(4-2)
目录 global头文件 global.h xx.h global头文件 插件的本质就是动态链接库,对于库,需要导出符号,供用户导入使用.在qt creator的源码中,存在固定的导入导出模式. gl ...
- Face The Right Way 开关(POJ3276)
描述: \( N 头牛排成了一列.每头牛或者向前或者向后.为了让所有的牛都面向前方,农夫约翰买了 一台自动转向的机器. 这个机器在购买时就必须设定一个数值 K,机器每操作一次恰好使 K 头连续的牛转向 ...
- 王颖奇 20171010129《面向对象程序设计(java)》第十三周学习总结
实验十三 图形界面事件处理技术 实验时间 2018-11-22 1.实验目的与要求 (1) 掌握事件处理的基本原理,理解其用途: (2) 掌握AWT事件模型的工作机制: (3) 掌握事件处理的基 ...
- 美团分布式ID生成框架Leaf源码分析及优化改进
本文主要是对美团的分布式ID框架Leaf的原理进行介绍,针对Leaf原项目中的一些issue,对Leaf项目进行功能增强,问题修复及优化改进,改进后的项目地址在这里: Leaf项目改进计划 https ...