HashMap底层相关内容

HashMap的底层结构:
1.7之前 数组加链表,当两个值进行插入的时候 采用头插法进行插入,可能会造成死循环
1.8之后 数组加链表/红黑树,当两个值进行插入的时候,采用尾插法进行插入,不会造成死循环

HashMap底层put源码:

  • 1.7之前 会先进行判断当前插入的值的key是否为null,如果是null
    检查数组为0的索引下标位置是否为空,如果不是空,就会把原来的值取出来放入oldValue返回回去,并采用头插法将新put的值放到原来的位置上,旧的值放到新值下面。
    如果是空,就会直接把put的值放入索引下标的位置上。
    如果key不为null会根据key调用方法indexFor计算出当前key所要存储的数组的索引下标的值,在判断当前下标下是否有元素,重复上面的操作,
    如果有的话还要进行判断当前的key是否存在,如果存在就直接覆盖并返回之前的值。
    之后将modCount加一,为了判断集合在迭代的时候,值是否发生了修改
    之后就会添加一个新的链表节点,添加之前先判断当前的数组用了多少,
    如果当前已用的数组位置达到了数组长度的0.75并且即将添加位置不为空就会发生扩容机制,没有达到会头插法添加元素,size++
  • 1.8之后 会先进行hash运算取出hash值,再判断当前hashMap的数组是否为空,如果为空初始化数组
    判断当前数组索引位置的值是否为空,如果为空,新建加入一个节点
    如果不为空,判断当前索引下标位置的元素是否与新put的值的key相同,如果相同,将值取出来放到e中
    如果不相同,判断当前索引下标位置的节点是否是树节点,如果是,去调用树方法去判断 加入节点等
    如果不是树节点,表示是链表节点,进行循环遍历,将p.next给e,如果e是空的话,直接将put进来的值插入到p.next位置,并判断是否已经达到了树化阈值
    达到了树化阈值了判断数组长度是否达到了64,数组长度也达到了进行树化,跳出循环
    如果e不为空,判断e的hash值是否和put进来的值的key的hash一样,如果相同,直接跳出循环
    将e的值放到一个oldValue中进行返回
    修改modCount的值进行++,size进行++,判断size的值是否达到了扩容情况,进行扩容。

HashMap在1.8的时候为什么要转换为红黑树?
因为在1.7的时候如果出现hash冲突就会将冲突的数据加入到链表中,如果冲突的数据多了,链表的数据就会太长,这样的话就会造成查询效率下降
红黑树的查询效率大于链表。红黑树的加入是为了解决hash冲突,提高查询效率。

树化阈值为什么是8?
这涉及到一个泊松分布,有人调查过,如果阈值达到8的时候,造成hash冲突的概率是千万分之一级别,冲突的概率就已经很小了

反树化阈值为什么是6?
因为如果反树化阈值是8,这样不太稳定,如果数组的同一节点在加上一个数就会导致进行树化,而如果减少一个数就会进行链表化,这样来回树化和反树化,会导致性能降低
而如果反树化阈值太小,很少的数就会导致转换成红黑树,完全没必要

加载因子为什么是0.75?
这是对时间和空间之间取得一个折中值,如果太大了是1的话,会导致hash冲突增加,降低性能,浪费时间
如果太小,是0.5的话,会导致还有一半的空间没有用就进行扩容,浪费空间

hashmap默认初始化大小是多少?为什么按照2的幂次方进行扩容?
初始化大小是16,因为2的幂次方-1是多个1的组合,就像1111,当获取添加元素到数组的哪一个索引下标的时候用hash码的值和2的幂次方-1进行取余运算,因为是取余运算
在相同的位置上,hash码值是什么,结果就是什么,降低了得到同一索引下标的可能性,也就降低了hash冲突。

hashmap扩容的条件?
当数组中插入元素的长度达到数组的长度*加载因子的时候会进行扩容
当同一个索引下标位置链表的长度达到8并且数组的长度还没有达到64的时候

hashmap是怎么进行扩容的?1.7
hashMap的初始化容量如果不是2的幂次方,实际初始化容量会是接近自定义初始化容量的最小的2的幂次方
按照原数组长度的2倍进行扩容,会将原来的数组的索引下标位置的部分元素转移的原数组索引下标位置加上原数组的长度的位置上
先进行循环遍历要进行转移的数组的索引下标,里面在进行循环遍历要转移的数据
将e指向要进行转移的元素,将next指向e的下一个元素,在将e.next指向要转移的新数组的对应下标位置,再将e赋值给新数组的对应索引下标,相当于是往下移了一位,
再将next的值赋给e,再次执行同样的操作。

为什么hashMap在1.7的时候采用头插法,在1.8变成了尾插法?
因为在高并发情况下,在扩容进行数据转移的时候,使用头插法可能导致next指向已经转移到新数组的数据,再次使用e.next指向新数组索引下标的时候,
的是链表上面的元素,导致成为一个环,造成了死循环。
而使用尾插法不会导致这样的情况。

hashMap里面的key和value可以是空值吗?
key和value都可以是空值,但是key只能有一个是空值

HashMap是线程安全的吗?
不是线程安全的,但是可以通过使用Collections的synchronizedMap()变得线程安全,也可以使用copyOnWrite变得线程安全

HashMap和HashTable的区别是什么?
HashMap是线程不安全的,HashTable是线程安全的
HashMap允许Key和Value为空,HashTable不允许键或值为空,如果键为空会报空指针异常
HashMap遍历的顺序不确定,HashTable的遍历顺序是按照插入的顺序进行遍历的
HashMap的性能相对较高一点,HashTable的性能相对较低

HashMap和LinkedHashMap的区别?
HashMap是无序的,获取的顺序和插入顺序不一致,LinkedHashMap是有序地,获取元素的顺序和插入顺序是一致的
HashMap底层就是数组加链表/红黑树,LinkedHashMap的底层是在HashMap的基础上维护了一个双向链表

HashMap和ConcurrentHashMap的区别是什么?
HashMap是线程不安全的,ConcurrentHashMap是线程安全的
HashMap由于线程不安全,所以并发情况下可能导致数据不一致或抛出异常,ConcurretHashMap使用了分段锁,所以不同的段可以被不同的线程访问,提高了并发性
HashMap没有锁,要保证线程安全需要再外部加上同步机制,ConcurrentHashMap使用了分段式锁, 锁得到粒度小
HashMap:在扩容时需要重新计算哈希值,重新分配元素位置,可能会导致链表长度过长,影响性能。ConcurrentHashMap:在扩容时只需要对某个段进行扩容,不会影响其他段,减少了扩容带来的性能损耗。

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

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

相关文章

xml转map工具类

背景&#xff1a;最近遇到接口返回是xml&#xff0c;所以需要整一个转换的工具类&#xff0c;方便后续其他xml处理。 依赖引入&#xff1a; <dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.1</versi…

澎峰科技|邀您关注2023 RISC-V中国峰会!

峰会概览 2023 RISC-V中国峰会&#xff08;RISC-V Summit China 2023&#xff09;将于8月23日至25日在北京香格里拉饭店举行。本届峰会将以“RISC-V生态共建”为主题&#xff0c;结合当下全球新形势&#xff0c;把握全球新时机&#xff0c;呈现RISC-V全球新观点、新趋势。 本…

linux下nginx配置https和反向代理本地端口

1 修改配置文件/etc/nginx/sites-enabled/default 在配置文件中增加一个server用来做https端口监听&#xff0c; ssl_certificate和ssl_certificate_key修改为自己申请的https认证文件 server{listen 443 ssl;server_name www.dogrich.net;#root /var/www/html;# 上面配置的…

《3D 数学基础》12 几何图元

目录 1 表达图元的方法 1.1 隐式表示法 1.2 参数表示 1.3 直接表示 2. 直线和射线 2.1 射线的不同表示法 2.1.1 两点表示 2.1.2 参数表示 2.1.3 相互转换 2.2 直线的不同表示法 2.2.1 隐式表示法 2.2.2 斜截式 2.2.3 相互转换 3. 球 3.1 隐式表示 1 表达图元的方…

C语言的使用技巧--在IO操作中的移位和快速配置

在WB32F103&#xff08;ARM cortex m3内核&#xff0c;96Mhz&#xff09;的gpio初始化中有一段代码&#xff0c;充分的结合了硬件特征并使用C语言的技巧来快速的配置对应的GPIO的功能&#xff0c;堪称经典和楷模&#xff0c;代码异常简洁&#xff0c;执行速度快&#xff0c;配置…

【深度学习所有损失函数】在 NumPy、TensorFlow 和 PyTorch 中实现(2/2)

一、说明 在本文中&#xff0c;讨论了深度学习中使用的所有常见损失函数&#xff0c;并在NumPy&#xff0c;PyTorch和TensorFlow中实现了它们。 (二-五)见 六、稀疏分类交叉熵损失 稀疏分类交叉熵损失类似于分类交叉熵损失&#xff0c;但在真实标签作为整数而不是独热编码提…

Python pycparser(c文件解析)模块使用教程

文章目录 安装 pycparser 模块模块开发者网址获取抽象语法树1. 需要导入的模块2. 获取 不关注预处理相关 c语言文件的抽象语法树ast3. 获取 预处理后的c语言文件的抽象语法树ast 语法树组成1. 数据类型定义 Typedef2. 类型声明 TypeDecl3. 标识符类型 IdentifierType4. 变量声明…

语聚AI公测发布,大语言模型时代下新的生产力工具

语聚AI 公测发布 距离语聚AI内测上线已经过去近1个月。 这期间&#xff0c;我们共邀请了近百位资深用户与行业专家加入语聚AI产品体验。通过大家的热情参与积极反馈&#xff0c;我们不断优化并完善了语聚AI的功能与使用体验。 经过研发团队不懈的努力&#xff0c;今天语聚AI终…

【Leetcode】88.合并两个有序数组

一、题目 1、题目描述 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 注意:最终,合并后数组不应由函数返回,而是存储在数…

梅赛德斯-奔驰将成为首家集成ChatGPT的汽车制造商

ChatGPT的受欢迎程度毋庸置疑。OpenAI这个基于人工智能的工具&#xff0c;每天能够吸引无数用户使用&#xff0c;已成为当下很受欢迎的技术热点。因此&#xff0c;有许多公司都在想方设法利用ChatGPT来提高产品吸引力&#xff0c;卖点以及性能。在汽车领域&#xff0c;梅赛德斯…

代码随想录算法训练营第59天|动态规划part16|583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇

代码随想录算法训练营第59天&#xff5c;动态规划part16&#xff5c;583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇 583. 两个字符串的删除操作 583. 两个字符串的删除操作 思路&#xff1a; 思路见代码 代码&#xff1a; python class Solution(object):de…

[国产MCU]-BL602开发实例-I2C与总线设备地址扫描

I2C与总线设备扫描 文章目录 I2C与总线设备扫描1、I2C介绍2、I2C驱动API介绍3、I2C使用实例I2C (Inter-Intergrated Circuit)是一种串行通讯总线,使用多主从架构,用来连接低速外围装置。 每个器件都有一个唯一的地址识别,并且都可以作为一个发送器或接收器。每个连接到总线的…

node-sass是什么

一、Sass&#xff08;Syntactically Awesome Style Sheets&#xff09; 是一种CSS预处理器&#xff0c;它扩展了CSS的功能并提供了更强大的样式表语言。Sass允许开发人员使用变量、嵌套规则、混合&#xff08;Mixins&#xff09;、继承等高级功能来编写更简洁、可维护的样式代…

2023年国赛数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…

QT-Mysql数据库图形化接口

QT sql mysqloper.h qsqlrelationaltablemodelview.h /************************************************************************* 接口描述&#xff1a;Mysql数据库图形化接口 拟制&#xff1a; 接口版本&#xff1a;V1.0 时间&#xff1a;20230727 说明&#xff1a;支…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)九:自定义组件封装下

一、本章内容 续上一张,本章实现一些自定义组件的封装,包括文件上传组件封装、级联选择组件封装、富文本组件封装等。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 基于VUE3+Layui从头搭建通用后台管

【软件工程】内聚

概念 是指一个模块内部个成分之间相互关联程度的度量。也就是说&#xff0c;凝聚是对模块内各处理动作组合强度的一种度量。很显然&#xff0c;一个模块的内聚越大越好。 偶然凝聚 一个模块内的各处理元素之间没有任何联系&#xff0c;只是偶然地被凑到一起。这种模块也称为…

mov转mp4格式怎么转?

mov转mp4格式怎么转&#xff1f;众所周知&#xff0c;MOV视频格式是由苹果公司推出的常用的视频格式&#xff0c;能够在苹果软件及设备上使用。但是&#xff0c;如果将其应用于其他软件和设备上的话&#xff0c;可能会遇到文件无法正常播放的情况。在这个时候&#xff0c;我们需…

Linux MQTT智能家居项目(LED界面的布局设置)

文章目录 前言一、LED界面布局准备工作二、LED界面布局三、逻辑实现总结 前言 上篇文章我们完成了主界面的布局设置那么这篇文章我们就来完成各个界面的布局设置吧。 一、LED界面布局准备工作 首先添加LED灯光控制的图标。 将选择好的LED图标添加进来&#xff1a; 图标可以…

drawio导出矢量图

1.选中要导出的图 2.导出为pdf 3.用adobe打开pdf&#xff0c;另存为eps