HashMap源码详解与对比
前几天工作忙得焦头烂额时,同事问了一下关于Map的特性,刹那间懵了一下,紧接着就想起来了一些关于Map的一些知识,因为只要涉及到Collection集合类时,就会谈及Map类,因此理解好Map相关的知识是灰常重要的。
Collection集合类 与 Map类的层次结构,如下图:

Map是用来存储 Key-Value(K-V)键值对,且不允许Key重复。(JDK 1.8)
Map的子类包含Hashtable,HashMap,LinkedHashMap,TreeMap,EnumMap,J.U.C并发包下面包含ConcurrentHashMap,ConcurrentSkipListMap。
注:Hashtable是通过“synchronized”来实现同步,ConcurrentHashMap是通过“分段锁”来实现并发,ConcurrentSkipListMap是通过“跳表”来实现并发。
数据结构对比
JDK 1.7及之前,HashMap的底层是数组和链表结合使用,可以说其结构是单向链表构成的数组,即链表散列,又称拉链法,即数组中的每一个序列空间代表一链表,若在插入新元素时,如果哈希冲突,则将新的元素插入到冲突的序列空间的链表头部。

JDK 1.8之后,HashMap的底层是数组链表和二叉树结合使用,其结构是先以链表结构进行存储,如果当链表的节点数(阈值)大于等于8时,再将其转换为二叉树结构,若该二叉树结构的节点数大于64,则再次resize,触发rehash操作,重新分布节点。

JDK 1.7 | 1.8 HashMap 方法分析

1. hashmap在JDK1.7|1.8中hash()方法优化:此处参考博客链接_hashmap冲突的解决方法以及原理分析
其实关于hash优化以及为什么是2的次幂,能理解,但是总归没有辣么详细,所以就参考了其他博主的博客,如果不合适,还请提出,会进行删除的。

2. hashmap在JDK中resize()方法
当HashMap的长度超过临界值时(默认16*0.75=12),就会进行扩容。
通过调用resize()方法重新创建一个原HashMap大小的两倍的元素数组newTable,最大扩容到 MAXIMUM_CAPACITY = 1 << 30,并将原先table的元素全部移到newTable里面,重新计算hash,然后再重新根据hash分配位置。这个过程叫作rehash(最消耗性能的操作),因为它重新调用hash方法找到新的bucket位置。所以创建HashMap的时候,如果能预知元素个数,应尽量指定初始容量,这样可以提高HashMap的性能,避免重复resize()、rehash造成的性能损耗。
若在多线程情况下,多个线程同时出发resize()方法,会造成死循环操作

通过上面的解析,可以得到使用的是2次幂的扩展(指长度扩为原来2倍),所以,元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置。
因此,我们在扩充HashMap的时候,不需要像JDK1.7的实现那样重新计算hash,通过使用(e.hash & oldCap)来计算高位和低位的hash值,来把原来在一个槽位上面的链表拆分成两个链表即可。
有一点注意区别,JDK1.7中rehash的时候,旧链表迁移新链表的时候,如果在新表的数组索引位置相同,则链表元素会倒置,但是从上图可以看出,JDK1.8不会倒置。
3. hashmap线程不安全,效率高
HashMap线程是不安全的,如果在多线程环境下,会出现未知异常(谨记)。
如果要在多线程情况下使用Map,有以下几种可供选择:
①、使用Hashtable(类中方法全是synchronized,效率特低,没有过这种);
②、使用Collections.synchronizedMap(new HashMap(...));实现,但不建议使用,使用迭代器遍历的时候修改映射结构容易出错;
③、使用guava中ImmutableMap,它是线程安全的,且方便快捷的组装键值对(建议);
ImmutableMap<String, Integer> map1 = ImmutableMap.<String, Integer>builder().put("A", 1) .put("B"2) .put("C", 3) .build();
ImmutableMap<String, Integer> map2 = ImmutableMap .<String, String>of("X", 0);
④、使用java.util.concurrent.ConcurrentHashMap,采用分段锁(JDK1.7) / CAS(JDK1.8)、相对安全,效率高(建议);
4. hashmap其他方法解析
其他方法后续有时间在进行补充...
JDK 中 HashMap 的其他问题
暂未想到,如有错误,还请指正 ...
HashMap源码详解与对比的更多相关文章
- Java HashMap源码详解
Java数据结构-HashMap 目录 Java数据结构-HashMap 1. HashMap 1.1 HashMap介绍 1.1.1 HashMap介绍 1.1.2 HashMap继承图 1.2 H ...
- HashMap源码详解(JDK7版本)
一.内部属性 内部属性源码: //内部数组的默认初始容量,作为hashmap的初始容量,是2的4次方,2的n次方的作用是减少hash冲突 static final int DEFAULT_INITIA ...
- Shiro 登录认证源码详解
Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...
- Activiti架构分析及源码详解
目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...
- 源码详解系列(七) ------ 全面讲解logback的使用和源码
什么是logback logback 用于日志记录,可以将日志输出到控制台.文件.数据库和邮件等,相比其它所有的日志系统,logback 更快并且更小,包含了许多独特并且有用的特性. logback ...
- Mybatis源码详解系列(四)--你不知道的Mybatis用法和细节
简介 这是 Mybatis 系列博客的第四篇,我本来打算详细讲解 mybatis 的配置.映射器.动态 sql 等,但Mybatis官方中文文档对这部分内容的介绍已经足够详细了,有需要的可以直接参考. ...
- vue 源码详解(二): 组件生命周期初始化、事件系统初始化
vue 源码详解(二): 组件生命周期初始化.事件系统初始化 上一篇文章 生成 Vue 实例前的准备工作 讲解了实例化前的准备工作, 接下来我们继续看, 我们调用 new Vue() 的时候, 其内部 ...
- RocketMQ源码详解 | Producer篇 · 其二:消息组成、发送链路
概述 在上一节 RocketMQ源码详解 | Producer篇 · 其一:Start,然后 Send 一条消息 中,我们了解了 Producer 在发送消息的流程.这次我们再来具体下看消息的构成与其 ...
- RocketMQ源码详解 | Broker篇 · 其一:线程模型与接收链路
概述 在上一节 RocketMQ源码详解 | Producer篇 · 其二:消息组成.发送链路 中,我们终于将消息发送出了 Producer,在短暂的 tcp 握手后,很快它就会进入目的 Broker ...
随机推荐
- Linux之创建777权限的文件
服务器中运行项目的时候,有时候会出现图片上传失败,查看报错原因才知道是文件夹没有写入权限导致上传失败. 方案1: 在使用Linux命令更改对应目录的权限 方案2: 在代码中创建文件夹的时候给予对应的7 ...
- Python-OpenCV中VideoCapture类的使用
目录 主要记录Python-OpenCV中的VideoCapture类的使用:官方文档: VideoCapture()是用于从视频文件.图片序列.摄像头捕获视频的类: #!/usr/bin/e ...
- python的发音
我一直读的是:拍方(可能是受有道词典发音的影响了~),可是别人都听不懂,他们大多是读的拍森. 来看看下面这个小伙伴的解释,感觉他说的挺好: “θ”这个字符的发音,有 80% 的中国人(学英文的人)都读 ...
- cenos php执行pdf2swf 配置环境
1.第一步:安装xpdf语言包 1.mkdir –p /usr/share/xpdf 2.cd /usr/share/xpdf/ 3.下载中文支持及字体库wget ftp://ftp.foolabs. ...
- Chrome插件-Postman Interceptor
postman有一个chrome插件 Postman Interceptor,可以让postman中发送请求的时候使用这个网站的浏览器cookie Postman Interceptor,可以让pos ...
- atcoder 2579
You are taking a computer-based examination. The examination consists of N questions, and the score ...
- 17.Merge Two Binary Trees(合并两个二叉树)
Level: Easy 题目描述: Given two binary trees and imagine that when you put one of them to cover the ot ...
- 图片滚动插件jquery bxslider
https://www.cnblogs.com/axl234/p/4167196.html
- C#空接合操作符——??
操作符: ?? 用法:C = A ?? B; 解释:if(A != null){ C=A;} else{C=B} 类似三元运算符 :? 例子: Int32? num1=null; Int32? ...
- Autel MaxiSys MS908CV Diagnostic System for Commercial Vehicles
As a new member of Autel’s MaxiSys family, the MaxiSys CV is built on the powerful MaxiSys 908 platf ...