java7,java8 中HashMap和ConcurrentHashMap简介
一:Java7 中的HashMap
结构:
HashMap 里面是一个数组,然后数组中每个元素是一个单向链表。链表中每个元素称为一个Entry 实例,Entry 包含四个属性:key, value, hash 值和用于单向链表的 next。
属性:
capacity:当前数组容量,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍。
loadFactor:负载因子,默认为 0.75。
threshold:扩容的阈值,等于 capacity * loadFactor
(一)put操作大概过程
在第一个元素插入 HashMap 的时候做一次数组的初始化,就是先确定初始的数组大小,并计算数组扩容的阈值。通过hash(key)找到数组下标后,会先进行 key 判重,如果没有重复,就准备将新值放入到链表的表头。主要逻辑就是先判断是否需要扩容,需要的话先扩容,然后再将这个新的数据插入到扩容后的数组的相应位置处的链表的表头。数组扩容
在插入新值的时候,如果当前的 size 已经达到了阈值(capacity * loadFactor),并且要插入的数组位置上已经有元素,那么就会触发扩容,扩容后,数组大小为原来的 2 倍。
(二)get 操作大概过程
①根据 key 计算 hash 值。
②找到相应的数组下标:hash & (length – 1)。
③遍历该数组位置处的链表,直到找到相等(==或equals)的 key。
二:Java7 中的ConcurrentHashMap
ConcurrentHashMap采用了分段锁的设计,只有在同一个分段内才存在竞态关系,不同的分段锁之间没有锁竞争。相比于对整个Map加锁的设计,分段锁大大的提高了高并发环境下的处理能力。
结构:
整个 ConcurrentHashMap 由一个个 Segment 组成,Segment 代表”部分“或”一段“的意思,所以很多地方都会将其描述为分段锁。每一个Segment中又存储一个类似HashMap的数组链表结构,可以简称为外层数组里面又一个内层数组,内层数组中是一个链表,这样的三维结构。
属性:
concurrencyLevel:Segment 数,默认是 16,也就是说 ConcurrentHashMap 有 16 个 Segments,最多可以同时支持 16 个线程并发写,只要它们的操作分别分布在不同的 Segment 上。这个值可以在初始化的时候设置为其他值,但是一旦初始化以后,它是不可以扩容的。
initialCapacity:初始容量,这个值指的是整个 ConcurrentHashMap 的初始容量,实际操作的时候需要平均分给每个 Segment。
loadFactor:负载因子,之前我们说了,Segment 数组不可以扩容,所以这个负载因子是给每个 Segment 内部使用的。
(一)put操作大概过程
①计算key的hash值确定在某个Segment写
②获得锁,也就是分段锁,操作确定的segment的时,不允许其他线程操作
③和HashMap的操作一样
对于扩容的操作,segment的容量一旦确定后是不能修改的,只能扩容segment [ i ] ,也是和HashMap一样的操作。
(二)get操作大概过程
①计算 hash 值,找到 segment 数组中的具体位置
②segment 中也是一个数组,根据 hash 找到数组中具体的位置
③到这里是链表了,顺着链表进行查找即可
三:Java8 中的HashMap
Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑树,所以其由 数组+链表+红黑树 组成。根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的具体下标,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度,为 O(n)。为了降低这部分的开销,在 Java8 中,当链表中的元素超过了 8 个以后,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)。
Java7 中使用 Entry 来代表每个 HashMap 中的数据节点,Java8 中使用 Node,基本没有区别,都是 key,value,hash 和 next 这四个属性,不过,Node 只能用于链表的情况,红黑树的情况需要使用 TreeNode。
结构:
Java8 中的HashMap里面是一个数组,然后数组中每个元素是一个单向链表,或者是一颗红黑树。当链表长度大于8时转化为红黑树
(一)put操作大概过程
①第一次插入初始化(默认16),不是第一次则计算hash(key)计算下标(判断是否需要扩容)
②判断下标的第一个节点是否是红黑树节点TreeNode ,如果是按照红黑树的插入规则插入。
③如果不是红黑树节点,而是链表节点Node,再判断加入节点后是否大于8。如果是转化为红黑树结构,如果不是,则比较并插入。
扩容也是超过阀定值,则扩容为原来的两倍。
(二)get操作大概过程
①计算 key 的 hash 值,根据 hash 值找到对应数组下标
②判断数组该位置处的元素是否刚好就是我们要找的,如果不是,走第三步
③判断该元素类型是否是 TreeNode,如果是,用红黑树的方法取数据,如果不是,走第四步
⑥遍历链表,直到找到相等(==或equals)的 key
四:Java8 中的ConcurrentHashMap
结构:
和 Java8 的 HashMap 基本上一样,里面是一个数组,然后数组中每个元素是一个单向链表,或者是一颗红黑树。当链表长度大于8时转化为红黑树
(一)put操作大概过程
①如果没有初始化就先调用initTable()方法来进行初始化过程
②如果没有hash冲突就直接CAS插入
③如果还在进行扩容操作就先进行扩容
④如果存在hash冲突,就加锁来保证线程安全,这里有两种情况,一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入,
⑤最后一个如果该链表的数量大于阈值8,就要先转换成黑红树的结构,break再一次进入循环
⑥如果添加成功就调用addCount()方法统计size,并且检查是否需要扩容
(二)get操作大概过程
①计算hash值,定位到该table索引位置,如果是首节点符合就返回
②如果遇到扩容的时候,会调用标志正在扩容节点ForwardingNode的find方法,查找该节点,匹配就返回
③以上都不符合的话,就往下遍历节点,匹配就返回,否则最后就返回null
java7,java8 中HashMap和ConcurrentHashMap简介的更多相关文章
- Java7/8 中 HashMap 和 ConcurrentHashMap的对比和分析
大家可能平时用HashMap比较多,相对于ConcurrentHashMap 来说并不是很熟悉.ConcurrentHashMap 是 JDK 1.5 添加的新集合,用来保证线程安全性,提升 Map ...
- java8中hashMap
摘自:http://www.importnew.com/20386.html 简介 Java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMa ...
- Java8中HashMap扩容算法小计
Java8的HashMap扩容过程主要就是集中在resize()方法中 final Node<K,V>[] resize() { // ...省略不重要的 } 其中,当HashMap扩容完 ...
- Java中HashMap与ConcurrentHashMap的区别
从JDK1.2起,就有了HashMap,正如前一篇文章所说,HashMap不是线程安全的,因此多线程操作时需要格外小心. 在JDK1.5中,伟大的Doug Lea给我们带来了concurrent包,从 ...
- Java7与Java8中的HashMap和ConcurrentHashMap知识点总结
JAVA7 Java7的ConcurrentHashMap里有多把锁,每一把锁用于其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率呢.这 ...
- Java7 和 Java8 中的 ConcurrentHashMap 原理解析
Java7 中 ConcurrentHashMap ConcurrentHashMap 和 HashMap 思路是差不多的,但是因为它支持并发操作,所以要复杂一些. 整个 ConcurrentHash ...
- Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析
Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析 今天发一篇”水文”,可能很多读者都会表示不理解,不过我想把它作为并发序列文章中不可缺少的一块来介绍.本来以为花不了 ...
- Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析 (转)
阅读前提:本文分析的是源码,所以至少读者要熟悉它们的接口使用,同时,对于并发,读者至少要知道 CAS.ReentrantLock.UNSAFE 操作这几个基本的知识,文中不会对这些知识进行介绍.Jav ...
- Java7/8 中的 HashMap 和 ConcurrentHashMap
Java7 HashMap 数组+链表 Java7 ConcurrentHashMap Segment数组+HashEntry数组链表+ReenTrantLock分段锁 Java8 HashMa ...
随机推荐
- net面试宝典
ASP.NET常见面试题及答案 1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private : 私有成员, 在类的内部才可以访问. ...
- PAT甲题题解-1012. The Best Rank (25)-排序水题
排序,水题因为最后如果一个学生最好的排名有一样的,输出的课程有个优先级A>C>M>E那么按这个优先级顺序进行排序每次排序前先求当前课程的排名然后再与目前最好的排名比较.更新 至于查询 ...
- PAT-1045. Favorite Color Stripe (30)-LIS
将Eva喜欢的颜色按顺序编个优先级, 2 3 1 5 6-> 1 2 3 4 5 然后读取stripe,将Eva不喜欢的先剔除掉,剩下的颜色替换为相应的优先级 2 2 4(去掉) 1 5 5 6 ...
- 20135220谈愈敏Blog4_系统调用(上)
系统调用(上) 谈愈敏 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 用户态 ...
- PAT-1001 采花生
题目描述 鲁宾逊先生有一只宠物猴,名叫多多.这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!——熊字”. 鲁宾逊先生和多多都很开心,因为花生正是他 ...
- ios UnitTest 学习笔记
一.运行第一个单元测试: 1.在Xcode 5中新建一个工程默认自带一个单元测试的文件夹,IDE自动生成了一个实现XCTestCase的.m文件,里面有一个失败测试(早期版本中实现的是SenTestC ...
- “数学口袋精灵”App的第一个Sprint计划
一.现状 我们这个团队想制作一个关于运算的游戏类型手机软件,针对我们这个学期的Android软件开发的课程,制作出一个关于数学算术游戏软件. 二.任务认领 第一阶段先把静态网页制作出来,各自的任务: ...
- 《当大数据遇见网络:大数据与SDN》
总体结构: <当大数据遇见网络:大数据与SDN> 摘要 大数据和SDN无论是对于学术界还是工业界来说都极具吸引力.传统上人们都是分别在最前沿工作中研究这两个重要的领域.然而一方面,SDN的 ...
- 第十二周(12.01-12.04)----final评论I
1. 约跑App——nice!:作为final发布讲说的第一组,nice团队很不容易.虽然很早就来到了发布场地,为发布做准备.但是准备上还是有些不足.对于摄像头的不稳定,nice没有很好的解决.在演 ...
- node之post提交上传
post文件上传 multer 中间件 在node中 express为了性能考虑采用按需加载的方式,引入各种中间件来完成需求, 平时解析post上传数据时候,是用body-parse.但这个中间件有缺 ...