HashMap与ConcurrentHashMap

文章目录

  • HashMap
    • 1.1 HashMap 的数据结构?
    • 1.2 HashMap 的动态扩容
    • 1.3 Hash实现方法
    • 1.4 如何解决Hash冲突
  • ConcurrentHashMap

HashMap

1.1 HashMap 的数据结构?

哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点。当链表长度超过 8 时,链表转换为红黑树。

1.2 HashMap 的动态扩容

当HashMap中的元素个数超过临界值时会触发动态扩容(threashold(临界值)=capacity (容量大小)* loadfactor(装载因子)),扩容 resize2n :

  • table 数组大小是由 capacity 这个参数确定的,默认是16,也可以构造时传入,最大限制是1<<30;

  • loadFactor 是装载因子,主要目的是用来确认table 数组是否需要动态扩展,默认值是0.75(概率泊松分布),比如table 数组大小为 16,装载因子为 0.75 时,threshold 就是12,当 table 的实际大小超过 12 时,table就需要动态扩容;

  • 扩容时,调用 resize() 方法,将 table 长度变为原来的两倍(注意是 table 长度,而不是 threshold

  • 如果数据很大的情况下,扩展时将会带来性能的损失,在性能要求很高的地方,这种损失很可能很致命。

1.3 Hash实现方法

JDK 1.8 中,是通过 hashCode() 的高 16 位异或低 16 位实现的:``(h = k.hashCode()) ^ (h >>> 16)`,主要是从速度,功效和质量来考虑的,通过位移运算来提升Hash值的散列度,降低Hash冲突的概率从而减少系统的开销

1.4 如何解决Hash冲突

HashMap引入了链式寻址法来解决Hash冲突的问题,用尾插法将元素放在链表的尾部:如果链表长度超过阀值(TREEIFY THRESHOLD==8 && SIZE >=64),就把链表转成红黑树,链表长度低于6,就把红黑树转回链表

解决Hash冲突一般有三种解决方法:

  • 再Hash法:就是如果某个hash函数产生了冲突,再用另外一个Hash进行计算,比如布隆过滤器就采用了这种方法
  • 开放寻址法:就是直接从冲突的数组位置往下寻找一个空的数组下标进行数据存储,这个在TreadLocal里面有使用到
  • 建立公共溢出区,也就是把存在冲突的key统一放在一个公共溢出区里面

ConcurrentHashMap

HashMap在并发操作中会产生并发安全问题,如死循环问题、数据覆盖问题等。因此在并发操作时一般会采用ConcurrentHashMap来解决,ConcurrentHashMap 类是 Java并发包java.util.concurrent 中提供的一个线程安全且高效的 HashMap 实现
JDK 1.7 中使用分段锁(ReentrantLock + Segment + HashEntry),相当于把一个 HashMap 分成多个段,每段分配一把锁,这样支持多线程访问。锁粒度:基于 Segment,包含多个 HashEntry
在这里插入图片描述

JDK 1.8 中使用 CAS + synchronized + Node + 红黑树。锁粒度:Node(首结点)(实现 Map.Entry)。锁粒度降低了。

在这里插入图片描述
下面是put操作的源码:
在这里插入图片描述

  1. 根据 key 计算出 hashcode,然后开始遍历 table;
  2. 判断容器是否为空,如果为空就会使用Volatile+CAS来初始化,
  3. 如果不为空就会根据存储的元素计算该位置是否为空,如果根据存储元素的计算结果为空,就会利用CAS来设计该节点
  4. 如果当前位置的 hashcode == MOVED == -1,则需要进行扩容。
  5. 如果存储元素的计算结果不为空,就会使用 synchronized 加锁来进行实现,然后遍历并修改桶中的数据
  6. 如果数量大于 TREEIFY_THRESHOLD 则要转换为红黑树。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/874179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详细分析Springboot自定义启动界面(附Demo)

目录 前言1. banner.text1.1 配置文件关闭1.2 启动类关闭1.3 命令行关闭 2. 自定义Banner类3. 自动配置类4. 总结 前言 实现自定义启动动画是一项有趣的任务&#xff0c;虽然Spring Boot本身不提供内置的动画功能&#xff0c;但可以通过一些技巧来实现 以下主要以Demo的形式展…

三字棋游戏(C语言详细解释)

hello&#xff0c;小伙伴们大家好&#xff0c;算是失踪人口回归了哈&#xff0c;主要原因是期末考试完学校组织实训&#xff0c;做了俄罗斯方块&#xff0c;后续也会更新&#xff0c;不过今天先从简单的三字棋说起 话不多说&#xff0c;开始今天的内容 一、大体思路 我们都知…

pytest钩子hook使用2

pytest是一种用于编写单元测试的Python库。它允许程序员编写测试用例来验证代码的正确性&#xff0c;并提供了一系列的勾子&#xff08;hooks&#xff09;来在测试的不同阶段执行一些额外的操作。 使用pytest的勾子&#xff0c;可以在测试运行过程中插入自定义代码。下面是一些…

springSecurity学习之springSecurity注解使用

springSecurity注解使用 在使用springboot的时候&#xff0c;大家更习惯于使用注解来进行配置&#xff0c;那么springSecurity注解怎么使用呢 首先开启注解 EnableGlobalMethodSecurity(// Spring Security 开启注解securedEnabledtrue, // 开启Secured注解,会创建切点&…

MongoDB教程(十三):MongoDB覆盖索引

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言什么是覆盖…

数据结构(栈及其实现)

栈 概念与结构 栈&#xff1a;⼀种特殊的线性表&#xff0c;其只允许在固定的⼀端进⾏插⼊和删除元素操作。 进⾏数据插⼊和删除操作的⼀端称为栈顶&#xff0c;另⼀端称为栈底。栈中的数据元素遵守后进先出 LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&…

date hwclock

目录 1.查看操作系统时间和bios时间 2.将系统时间同步到硬件时钟 3.将硬件时间同步到系统时间 1.查看操作系统时间和bios时间 date && hwclock Wed Jun 26 23:05:19 CST 2024 Wed 26 Jun 2024 11:05:24 PM CST -0.380328 seconds 2.将系统时间同步到硬件时钟 #…

PyCharm创建一个空的python项目

1.设置项目路径 2.配置python解释器 右下角可以选择always

【Linux】线程——生产者消费者模型、基于阻塞队列的生产消费者模型、基于环形队列的生产消费者模型、POSIX信号量的概念和使用

文章目录 Linux线程6. 生产消费者模型6.1 基于阻塞队列的生产消费者模型6.1.1 阻塞队列模型实现 6.2 基于环形队列的生产消费者模型6.2.1 POSIX信号量的概念6.2.2 POSIX信号量的使用6.2.3 环形队列模型实现 Linux线程 6. 生产消费者模型 生产消费者模型的概念 生产者消费者模…

Jackson详解

文章目录 一、Jackson介绍二、基础序列化和反序列化1、快速入门2、序列化API3、反序列化API4、常用配置 三、常用注解1、JsonProperty2、JsonAlias3、JsonIgnore4、JsonIgnoreProperties5、JsonFormat6、JsonPropertyOrder 四、高级特性1、处理泛型1.1、反序列化List泛型1.2、反…

Java 写一个可以持续发送消息的socket服务端

前言 最近在学习flink, 为了模仿一个持续的无界的数据源, 所以需要一个可以持续发送消息的socket服务端. 先上效果图 效果图 socket服务端可以持续的发送消息, flink端是一个统计单词出现总数的消费端,效果图如下 源代码 flink的消费端就不展示了, 需要引入一些依赖和版本…

Linux系统编程基础

Linux操作系统 Linux不是一个具体的操作系统&#xff0c;而是一类操作系统的总称&#xff0c;具体版本成为发行版。 Red Hat&#xff1a;目前被IBM收购&#xff0c;收费版&#xff0c;目前最大的Linux供应商CentOS&#xff1a; Red Hat退出的免费版Ubuntu&#xff1a;界面比较友…

二十一、【机器学习】【非监督学习】- 谱聚类 (Spectral Clustering)​​

系列文章目录 第一章 【机器学习】初识机器学习 第二章 【机器学习】【监督学习】- 逻辑回归算法 (Logistic Regression) 第三章 【机器学习】【监督学习】- 支持向量机 (SVM) 第四章【机器学习】【监督学习】- K-近邻算法 (K-NN) 第五章【机器学习】【监督学习】- 决策树…

商品信息管理系统(C语言)

系统分析 该案例使用了C语言中最具特色的结构体&#xff0c;将每个商品的所有信息存在结构体中&#xff0c;并且定义一个结构体类型的数组保存所有商品的信息&#xff0c;并且按照模块化的编程思想&#xff0c;将要实现的每个功能编写成独立的函数&#xff0c;这样即方便阅读同…

hung 之 Android llkd

目录 1. llkd 简介 2. 原理 2.1 内核活锁 2.2 检测机制 2.3 为什么 persistent stack signature 检测机制不执行 ABA 检查&#xff1f; 2.4 为什么 kill 进程后&#xff0c;进程还存在就能判定发生了内核 live-lock&#xff1f; 3. 代码 3.1 内核 live-lock 检查 3.2 …

摸鱼大数据——用户画像——如何给用户“画像”

2、如何给用户“画像” 2.1 什么是标签体系 标签: 是某一种用户特征的符号表示 标签体系: 把用户分到多少类别里面去, 这些类是什么, 彼此之间有什么关系, 就构成了标签体系 标签解决的问题: 解决描述(或命名)问题以及解决数据之间的关联 2.2.1 标签的分类 用户画像标签一…

《Nginx核心技术》第04章:生成缩略图

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球项目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…

Vue学习---vue 防抖处理函数,是处理什么场景

Vue防抖处理函数是用来处理在快速连续操作中&#xff0c;只执行最后一次操作的情况。 例如&#xff0c;在输入框输入时&#xff0c;我们可能希望只在用户完成输入后进行处理&#xff0c;而不是在每次键入时都处理。(n秒后触发一次) 以下是一个简单的Vue防抖处理函数的例子&am…

今日总结:雪花算法,拉取在线用户

雪花算法&#xff1a; public class SnowflakeIdGenerator {private final long epoch 1626804000000L; // 定义起始时间戳&#xff0c;这里设置为2021-07-21 00:00:00 UTCprivate final long workerIdBits 5L; // 机器ID所占的位数private final long sequenceBits 10L; /…

【附源码】IMX6U嵌入式Linux开发板连接阿里云--MQTT协议

演示 IMX6U嵌入式Linux开发板连接阿里云 阿里云创建设备&&获取LinkSDK 如果还不知道怎么在阿里云创建设备和获取连接阿里云的LinkSDK的话&#xff0c;先看这篇文章&#xff0c;再到这里。看这篇文章的时候&#xff0c;麻烦将下方文章打开对照着看&#xff0c;因为一些…