HashMap学习总结

news2024/11/28 16:53:44

1. JDK 1.8 主要进行了哪些优化?

1)底层数据结构从“数组+链表”改成“数组+链表+红黑树”,主要是优化了 hash 冲突较严重时,链表过长的查找性能:O(n) -> O(logn)。

2)计算 table 初始容量的方式发生了改变,老的方式是从1开始不断向左进行移位运算,直到找到大于等于入参容量的值;新的方式则是通过“5个移位+或等于运算”来计算。

// JDK 1.7.0
public HashMap(int initialCapacity, float loadFactor) {
    // 省略
    // Find a power of 2 >= initialCapacity
    int capacity = 1;
    while (capacity < initialCapacity)
        capacity <<= 1;
    // ... 省略
}
// JDK 1.8.0_191
static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

3)优化了 hash 值的计算方式,老的通过一顿瞎JB操作,新的只是简单的让高16位参与了运算。

// JDK 1.7.0
static int hash(int h) {
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}
// JDK 1.8.0_191
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

4)扩容时插入方式从“头插法”改成“尾插法”,避免了并发下的死循环。

5)扩容时计算节点在新表的索引位置方式从“h & (length-1)”改成“hash & oldCap”,性能可能提升不大,但设计更巧妙、更优雅。

2. put流程

在这里插入图片描述

3. 扩容

在这里插入图片描述

4. HashMap 的容量必须是 2 的 N 次方,这是为什么?

(n - 1) & hash,当 n 为 2 的 N 次方时,n - 1 为低位全是 1 的值,此时任何值跟 n - 1 进行 & 运算的结果为该值的低 N 位,达到了和取模同样的效果,实现了均匀分布。实际上,这个设计就是基于公式:x mod 2^n = x & (2^n - 1),因为 & 运算比 mod 具有更高的效率。

5. HashMap是线程安全问题

在多线程环境下,1.7 会产生死循环、数据丢失、数据覆盖的问题,1.8 中会有数据覆盖的问题,以1.8为例,当A线程判断index位置为空后正好挂起,B线程开始往index位置的写入节点数据,这时A线程恢复现场,执行赋值操作,就把A线程的数据给覆盖了;还有++size这个地方也会造成多线程同时扩容等问题。

6. 解决线程不安全的问题

HashTable、Collections.synchronizedMap、以及ConcurrentHashMap可以实现线程安全的Map。
HashTable是直接在操作方法上加synchronized关键字,锁住整个数组,粒度比较大,
Collections.synchronizedMap是使用Collections集合工具的内部类,通过传入Map封装出一个SynchronizedMap对象,内部定义了一个对象锁,方法内通过对象锁实现;
ConcurrentHashMap使用分段锁,降低了锁粒度,让并发度大大提高。

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

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

相关文章

GLM 130B和chatGLM2-6B模型结构

GLM-130B 一、预训练 采用双向注意力机制&#xff0c;对被遮挡的部分及逆行预测&#xff0c; 可以自由设置单词mask,句子smask,文章gmask,可以根据任务的不同设置mask&#xff0c;文本理解设置单词级别mask&#xff0c;文本生成色湖之句子级别的gmask&#xff0c;glm130B中设置…

Streamsets binlog采集时区问题

通过Streamsets采集mysql binglog增量数据时候&#xff0c;出现数据库中datetime时区问题。 要注意一点是&#xff0c;streamsets的前端展示的时间也是有时区的&#xff0c;后端返回的数据是时间戳&#xff0c;等于做了两次时区的转换 后端binglog时区转换->时间戳->前端…

ELK日志记录——Kibana组件——grok 正则捕获插件

grok 正则捕获插件 grok 使用文本片段切分的方式来切分日志事件 内置正则表达式调用 %{SYNTAX:SEMANTIC} ●SYNTAX代表匹配值的类型&#xff0c;例如&#xff0c;0.11可以NUMBER类型所匹配&#xff0c;10.222.22.25可以使用IP匹配。 ●SEMANTIC表示存储该值的一个变量声明&…

Linux——SIGCHLD信号——第17号信号

目录 什么是僵尸进程? 僵尸进程的目的? 如何避免僵尸进程? 总结&#xff1a; 提到SIGCHLD信号&#xff0c;就不得不先说一个有关僵尸状态的进程知识点了。 什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存情区&#xff0c;关闭所有打开的文…

计代码行数cloc,一个代码统计行数很好用的工具

分为window、mac系统区分&#xff0c;基本是一样的&#xff0c;一个代码统计行数很好用的工具。 CLOC简介 Cloc是一款使用Perl语言开发的开源代码统计工具&#xff0c;支持多平台使用、多语言识别&#xff0c;能够计算指定目标文件或文件夹中的文件数&#xff08;files&#x…

Linux——sigaction信号捕捉函数

目录 一.sigaction () ; struct sigaction结构体的成员&#xff1a; sigaction()和signal()函数的区别&#xff1a; 二.sigaction函数的使用 sigaction函数使用案例1&#xff1a; 对该进程发送指定的信号 案例2&#xff1a;对该进程发送多个同类型的信号时&#xff1a; …

vim中文帮助文档安装

vim自带的帮助手册是英文的, 对平时编程的人来说没有多大阅读困难,在何况还有"星级译王"呢, 但是我猜和我一样连英语四级都愁的大有人&#xff0c;可偏偏就有一帮好心人人将其翻译成了中文, 可偏偏我又挡不住诱惑将它安装了, 唉.......又痛失一个学习英文的好机会, 下…

J2EE集合框架Map

目录 一.Map特点 1.无序&#xff0c;键值对&#xff0c;键不能重复&#xff0c;值可以重复 2.键重复则覆盖&#xff0c;没有继承Collection接口 二.遍历方式 1.拿到key,再拿值2.拿到映射关系&#xff0c;键值都有 取出保存所有Entry的Set,再遍历此Set即可 三.HashMap与H…

SpringBoot实现返回值数据脱敏

介绍 SpringBoot实现返回数据脱敏 有时&#xff0c;敏感数据返回时&#xff0c;需要进行隐藏处理&#xff0c;但是如果一个字段一个字段的进行硬编码处理的话&#xff0c;不仅增加了工作量&#xff0c;而且后期需求变动的时候&#xff0c;更加是地狱般的工作量变更。 下面&am…

HLS入门简述

What‘s HLS&#xff1f; HLS&#xff08;High-Level Synthesis&#xff09;高层次综合。何谓高层次&#xff1f;意味着我们可以使用高层次的语言来对设计进行描述&#xff0c;如C&#xff0c;C&#xff0c;System C等&#xff1b;那何谓综合呢&#xff1f;HLS在其中起了重要的…

Denosing score matching (公式+代码)

加噪声的分数匹配 def anneal_dsm_score_estimation(scorenet, samples, labels, sigmas, anneal_power2.):# 取出每个样本对应噪声级别下的噪声分布的标准差&#xff0c;即公式中的sigma_i&#xff0c;# 这里的 labels 是用于标识每个样本的噪声级别的&#xff0c;就是 i&…

JavaEE——常见的锁策略、CAS、synchronized 原理(八股)

文章目录 一、常见的锁策略1.乐观锁 & 悲观锁2.轻量级锁 & 重量级锁3.自旋锁 & 挂起等待锁4.互斥锁 & 读写锁5. 公平锁 & 非公平锁 二、CAS1、什么是 CAS2. CAS 的应用场景2.实现自旋锁3. CAS 中的 ABA 问题 三、 Synchronized 原理 一、常见的锁策略 当前…

DataFun: ChatGPT背后的模型详解

ChatGPT背后的模型详解 Overview Transofrmer 各个构件都有一定的作用 Multi-head self attention 每个字的重要性不一样&#xff0c;学习QKV三个矩阵&#xff08;query&#xff0c;key&#xff0c;value&#xff09; 多组QKV RLHF ChatGPT训练过程 思维链 COT

C++_简单模拟实现string的基本结构

C中&#xff0c;string早于STL问世。使用string中的构造函数可以实现对string类型的字符串的一系列操作。 今天来模拟C中的string的基本结构。注意仅仅是简单模拟&#xff0c;string内部结构其实非常复杂&#xff0c;并且不同版本的IDEstring的内部结构也不尽相同。尽管有所不…

SpringBoot2+Vue2实战(十五)高德地图集成

1.地图官网&#xff1a; 高德开放平台 | 高德地图API 2.开发文档(web js) 正式集成&#xff1a; 1.再index.html中引入script标签 <script type"text/javascript" src"https://webapi.amap.com/maps?v2.0&key您申请的key值"></script>…

第五章 PCIe介绍 5.1-5.7

5.1 从PCIe的速度说起 为什么SSD要用PCIe接口&#xff1f;因为它快&#xff0c;比SATA快。 Lane&#xff1a;通道&#xff0c;PCIe最多可以有32个通道。 1. PCIe的工作模式 两个设备之间的PCIe连接&#xff0c;叫做一个Link。如下图&#xff0c;设备A和设备B是个双向连接&#…

【读书笔记】只管去做

《只管去做》是一本很容易读完的书&#xff0c;这本书是以故事的形式来阐述把愿景落实到每天的行动中的方法&#xff0c;对我们做人生规划很有帮助。

使用leaflet在html中加载天地图且去掉左上角的缩放图标以及右下角的logo

前言 我们这一节使用轻量化的javascript库leaflet来实现在html中加载天地图&#xff0c;实现类似高德地图、百度地图的效果。 效果图如下&#xff1a; 话不多说&#xff0c;进入主题&#xff01;&#xff01; 一、注册开发者权限 我们需要在天地图平台注册一个账号&#xff0…

【Qt】VS2013+QT5.6.3环境搭建

安装VS2013 略 安装Qt 安装文件&#xff1a;qt-opensource-windows-x86-msvc2013-5.6.3.exe&#xff08;官网已经不提供下载了。&#xff09; 安装步骤&#xff1a;安装到C盘根目录&#xff0c;其它略。 安装qt vs插件 1、下载地址&#xff1a; https://download.qt.io/a…

string常见功能模拟

学到string终于就不用像c语言一样造轮子了&#xff0c;接下来我们就模拟一下string方便我们更好理解string&#xff0c;首先我们都知道库里有个string&#xff0c;所以为了避免我们的string和库里的冲突&#xff0c;要用命名空间my_string将我们写的string包含在内。string的成…