重新开始学习编程系列Day02——HashMap和ConcurrentHashmap

简介: 最近读了HashMap和ConcurrentHashmap的源码,以及花了两天时间看了这方面相关的视频,记录一下新get到的知识。以问答的方式记录。

前言

大家好,我是苍何。最近思考了一个问题,为什么会出现公司面试造火箭,工作扭螺丝的现象,包括各种八股文的连环大绝杀问到你不会为主,其实这是考察你的知识面以及掌握的深度,而为什么需要这样呢?归其原因,无非是通过筛选找到那些会思考的人,他们需要的并不是CRUD的工具人,而是会思考能创新的工程师。

当你深刻理解到这点,我想不用刻意去学习,在工作中,肯定会吾日三省吾身。

于是乎,这个重新开始学习编程系列文章出来了。

愿与君共勉!

最近读了HashMap和ConcurrentHashmap的源码,以及花了两天时间看了这方面相关的视频,记录一下新get到的知识。以问答的方式记录。

一、HashMap的特性

1、存储的是键值对,允许为null,key不可重复,重复则覆盖
2、非同步,线程不安全
3、底层hash表,不保证有序

二、HashMap的底层原理是什么?

1、JDK7扩容时候多线程情况下可能会出现死循坏,根本原因是头插法导致
2、hash种子默认0,可以配置变量来使得hash值更散列一些。
3、modCount++每一次修改都会加一
容错快速失败机制(fail fast,并发时候出现问题
4、1.8hashmap是尾插法,链表长度大于8会转为红黑树,即第九个来的时候,数组是空的或者数组长度小于64不会树化
5、hashmap1.7扩容条件多了一个判断当前数组节点不为空,均要判断是否大于阈值
6、红黑树节点个数小于6个会转为链表

三、hashmap 的底层数据结构

JDK7:数组+链表
JSK8:数组+链表+红黑树

四、JDK8中hashmap为什么要用红黑树

当元素个数在小于某一个阈值时,链表的插入查询效率高于红黑树,大于该阈值时,红黑树插入和查询效率高于链表,在hashmap中此阈值为8,即链表的长度大于8时,转为红黑树效率更高

五、JDK8中hashmap什么时候将链表转为红黑树

链表元素个数大于8,且数组的长度大于等于64时,才会将链表转为红黑树,数组长度小于64,会进行扩容

六、JDK8中hashmap中put方法的实现过程

在这里插入图片描述

七、JDK8中hashmap中get方法实现过程?

在这里插入图片描述

八、JDK7和JDK8中hashmap不同?

1、8中用到了红黑树
2、7中链表插入用头插法(扩容元素的时候使用的也是头插法,头插法速度更快,无需遍历链表,但是在多线程扩容的情况下会出现循坏链表的问题,导致CPU飙升),8中用尾插法(反正要遍历计算链表当前的结点个数)
3、7中hash算法更复杂,生成的hashcode更散列,hashmap中的元素更散列,查询性能更好,8中有红黑树简化hash算法,防止消耗CPU
4、扩容7可能rehash,和hash种子有关,8中无
5、7的扩容条件除了判断size是否大于阈值外,还判断tab【i】不为空,才扩容,8中仅仅判断size是否大于阈值

6、扩容转移元素逻辑不一致,7是一次转移,8是先算出高低位,再一次性转移

九、JDK7中ConcurrentHashmap是怎么保证并发安全的?

主要是利用Unsafe操作+ReentrantLock+分段思想

Unsafe:通过CAS修改对象属性,并发安全的给数组的某个位置赋值以及获取元素;
分段思想是为了提高并发量,分段数可以通过参数控制

十、JDK7中ConcurrentHashmap的底层原理

由两层嵌套数组实现的
1、ConcurrentHashmap对象中有一个属性segments,类型为segment[],
2、segment对象有一个属性table,类型为hashEntry[]
put方法十,先根据key计算segment[],数组下标,确定好当前key,value应该插入到哪个segment对象中,如果segment[],为空,利用自旋锁在该位置生成segment对象,然后再调用segment对象的put方法先加锁,根据key计算hashEntry[]数组下标,加锁先通过自加锁(trylock),如果超过一定次数就会加阻塞锁(lock())

十一、JDK8中ConcurrentHashmap是怎么保证线程安全的?

主要是unsafe操作+synchronized
对table[i]进行加锁

十二、JDK7和JDK8中ConcurrentHashmap不同点

1、8中没有分段锁了,而是通过synchronized来控制
2、8中扩容性能更高

目录
相关文章
|
4天前
|
存储 安全 Java
Java面试题:请解释Java内存模型,并说明如何在多线程环境下使用synchronized关键字实现同步,阐述ConcurrentHashMap与HashMap的区别,以及它如何在并发环境中提高性能
Java面试题:请解释Java内存模型,并说明如何在多线程环境下使用synchronized关键字实现同步,阐述ConcurrentHashMap与HashMap的区别,以及它如何在并发环境中提高性能
9 0
|
21天前
|
存储 缓存 安全
java编程hashmap详解
java编程hashmap详解
|
2月前
|
Java 索引
【JAVA学习之路 | 进阶篇】HashMap源码剖析
【JAVA学习之路 | 进阶篇】HashMap源码剖析
|
2月前
|
存储 C++
为什么HashMap的键值可以为null,而ConcurrentHashMap不行?
为什么HashMap的键值可以为null,而ConcurrentHashMap不行?
31 1
|
2月前
|
安全 Java 调度
HashMap很美好,但线程不安全怎么办?ConcurrentHashMap告诉你答案!
HashMap很美好,但线程不安全怎么办?ConcurrentHashMap告诉你答案!
56 1
|
2月前
|
Java 存储
键值之道:深入学习Java中强大的HashMap(二)
键值之道:深入学习Java中强大的HashMap
91 0
键值之道:深入学习Java中强大的HashMap(二)
|
2月前
|
存储 安全 Java
键值之道:深入学习Java中强大的HashMap(一)
键值之道:深入学习Java中强大的HashMap
50 0
键值之道:深入学习Java中强大的HashMap(一)
|
2月前
|
存储 并行计算 安全
【Java编程进阶之路 01】深入探索:HashMap、ConcurrentHashMap与HashTable的演进之路
HashMap、ConcurrentHashMap与HashTable均为Java中的哈希表实现。HashMap非线程安全但性能高,适用于单线程;HashTable线程安全但性能较低,已少用;ConcurrentHashMap线程安全且高性能,是并发环境下的首选。三者在线程安全性与性能间各有侧重。
51 1
|
2月前
|
存储 Java 索引
【Java编程进阶之路 03】深入探索:HashMap的长度为什么是2的幂次方
HashMap的长度为2的幂次方是为了利用位运算快速计算索引,提高数据分散性和减少哈希冲突。这样设计能确保元素均匀分布,提高搜索效率。同时,2的幂次方长度便于动态扩容时计算新位置,简化元素迁移过程。
77 0
|
2月前
|
存储 算法 Java
【深入挖掘Java技术】「源码原理体系」盲点问题解析之HashMap工作原理全揭秘(下)
在阅读了上篇文章《【深入挖掘Java技术】「源码原理体系」盲点问题解析之HashMap工作原理全揭秘(上)》之后,相信您对HashMap的基本原理和基础结构已经有了初步的认识。接下来,我们将进一步深入探索HashMap的源码,揭示其深层次的技术细节。通过这次解析,您将更深入地理解HashMap的工作原理,掌握其核心实现。
38 0
【深入挖掘Java技术】「源码原理体系」盲点问题解析之HashMap工作原理全揭秘(下)