前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java面试八股文宝典之基础篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day12

【Java面试八股文宝典之基础篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day12

作者头像
陶然同学
发布2023-02-24 13:19:34
1960
发布2023-02-24 13:19:34
举报
文章被收录于专栏:陶然同学博客
谈谈Concurrent(可考润s)HashMap的扩容机制

1.7版本

1. 1.7版本的ConcurrentHashMap是基于Segment(色们)分段实现的

2. 每个Segment相对于⼀个⼩型的HashMap

3. 每个Segment内部会进⾏扩容,和HashMap的扩容逻辑类似

4. 先⽣成新的数组,然后转移元素到新数组中

5. 扩容的判断也是每个Segment内部单独判断的,判断是否超过阈值

1.8版本

1. 1.8版本的ConcurrentHashMap不再基于Segment实现

2. 当某个线程进⾏put时,如果发现ConcurrentHashMap正在进⾏扩容那么该线程⼀起进⾏扩容

3. 如果某个线程put时,发现没有正在进⾏扩容,则将key-value添加到ConcurrentHashMap中,然

后判断是否超过阈值,超过了则进⾏扩容

4. ConcurrentHashMap是⽀持多个线程同时扩容的

5. 扩容之前也先⽣成⼀个新的数组

6. 在转移元素时,先将原数组分组,将每组分给不同的线程来进⾏元素的转移,每个线程负责⼀组

或多组的元素转移⼯作

Jdk1.7到Jdk1.8 HashMap 发⽣了什么变化(底层)?

1. 1.7中底层是数组+链表,1.8中底层是数组+链表+红⿊树,加红⿊树的⽬的是提⾼HashMap插⼊

和查询整体效率

2. 1.7中链表插⼊使⽤的是头插法,1.8中链表插⼊使⽤的是尾插法,因为1.8中插⼊key和value时

需要判断链表元素个数,所以需要遍历链表统计链表元素个数,所以正好就直接使⽤尾插法

3. 1.7中哈希算法⽐较复杂,存在各种右移与异或运算,1.8中进⾏了简化,因为复杂的哈希算法的

⽬的就是提⾼散列性,来提供HashMap的整体效率,⽽1.8中新增了红⿊树,所以可以适当的简化

哈希算法,节省CPU资源

说⼀下HashMap的Put⽅法

先说HashMap的Put⽅法的⼤体流程:

1. 根据Key通过哈希算法与与运算得出数组下标

2. 如果数组下标位置元素为空,则将key和value封装为Entry对象(

JDK1.7中是Entry对象,JDK1.8中是Node对象)并放⼊该位置

3. 如果数组下标位置元素不为空,则要分情况讨论

a. 如果是JDK1.7,则先判断是否需要扩容,如果要扩容就进⾏扩容,如果不⽤扩容就⽣成Entry

对象,并使⽤头插法添加到当前位置的链表中

b. 如果是JDK1.8,则会先判断当前位置上的Node的类型,看是红⿊树Node,还是链表Node

ⅰ. 如果是红⿊树Node,则将key和value封装为⼀个红⿊树节点并添加到红⿊树中去,在这个

过程中会判断红⿊树中是否存在当前key,如果存在则更新value

ⅱ. 如果此位置上的Node对象是链表节点,则将key和value封装为⼀个链表Node并通过尾插

法插⼊到链表的最后位置去,因为是尾插法,所以需要遍历链表,在遍历链表的过程中会

判断是否存在当前key,如果存在则更新value,当遍历完链表后,将新链表Node插⼊到链

表中,插⼊到链表后,会看当前链表的节点个数,如果⼤于等于8,那么则会将该链表转

成红⿊树

ⅲ. 将key和value封装为Node插⼊到链表或红⿊树中后,再判断是否需要进⾏扩容,如果需要

就扩容,如果不需要就结束PUT⽅法

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Jdk1.7到Jdk1.8 HashMap 发⽣了什么变化(底层)?
  • 说⼀下HashMap的Put⽅法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档