重新开始学习编程系列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中扩容性能更高

目录
相关文章
|
1月前
|
存储 开发者
HashMap和Hashtable的key和value可以为null吗,ConcurrentHashMap呢
HashMap的key可以为null,value也可以为null;Hashtable的key不允许为null,value也不能为null;ConcurrentHashMap的key不允许为null
|
1月前
|
存储 缓存 Java
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
34 1
|
3月前
|
存储 Java 开发者
HashMap线程安全问题大揭秘:ConcurrentHashMap、自定义同步,一文让你彻底解锁!
【8月更文挑战第24天】HashMap是Java集合框架中不可或缺的一部分,以其高效的键值对存储和快速访问能力广受开发者欢迎。本文深入探讨了HashMap在JDK 1.8后的底层结构——数组+链表+红黑树混合模式,这种设计既利用了数组的快速定位优势,又通过链表和红黑树有效解决了哈希冲突问题。数组作为基石,每个元素包含一个Node节点,通过next指针形成链表;当链表长度过长时,采用红黑树进行优化,显著提升性能。此外,还介绍了HashMap的扩容机制,确保即使在数据量增大时也能保持高效运作。通过示例代码展示如何使用HashMap进行基本操作,帮助理解其实现原理及应用场景。
55 1
|
3月前
|
安全 Java
【Java集合类面试十六】、HashMap与ConcurrentHashMap有什么区别?
HashMap是非线程安全的,而ConcurrentHashMap通过减少锁粒度来提高并发性能,检索操作无需锁,从而提供更好的线程安全性和性能。
|
3月前
|
开发者 C# UED
WPF与多媒体:解锁音频视频播放新姿势——从界面设计到代码实践,全方位教你如何在WPF应用中集成流畅的多媒体功能
【8月更文挑战第31天】本文以随笔形式介绍了如何在WPF应用中集成音频和视频播放功能。通过使用MediaElement控件,开发者能轻松创建多媒体应用程序。文章详细展示了从创建WPF项目到设计UI及实现媒体控制逻辑的过程,并提供了完整的示例代码。此外,还介绍了如何添加进度条等额外功能以增强用户体验。希望本文能为WPF开发者提供实用的技术指导与灵感。
142 0
|
4月前
|
安全 Java
多线程线程安全问题之避免ThreadLocal的内存泄漏,如何解决
多线程线程安全问题之避免ThreadLocal的内存泄漏,如何解决
|
4月前
|
存储 安全 Java
Java面试题:请解释Java内存模型,并说明如何在多线程环境下使用synchronized关键字实现同步,阐述ConcurrentHashMap与HashMap的区别,以及它如何在并发环境中提高性能
Java面试题:请解释Java内存模型,并说明如何在多线程环境下使用synchronized关键字实现同步,阐述ConcurrentHashMap与HashMap的区别,以及它如何在并发环境中提高性能
39 0
|
1月前
|
Java
让星星⭐月亮告诉你,HashMap中保证红黑树根节点一定是对应链表头节点moveRootToFront()方法源码解读
当红黑树的根节点不是其对应链表的头节点时,通过调整指针的方式将其移动至链表头部。具体步骤包括:从链表中移除根节点,更新根节点及其前后节点的指针,确保根节点成为新的头节点,并保持链表结构的完整性。此过程在Java的`HashMap$TreeNode.moveRootToFront()`方法中实现,确保了高效的数据访问与管理。
29 2
|
1月前
|
Java 索引
让星星⭐月亮告诉你,HashMap之往红黑树添加元素-putTreeVal方法源码解读
本文详细解析了Java `HashMap` 中 `putTreeVal` 方法的源码,该方法用于在红黑树中添加元素。当数组索引位置已存在红黑树类型的元素时,会调用此方法。具体步骤包括:从根节点开始遍历红黑树,找到合适位置插入新元素,调整节点指针,保持红黑树平衡,并确保根节点是链表头节点。通过源码解析,帮助读者深入理解 `HashMap` 的内部实现机制。
33 2
|
1月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
52 0