Java中hashmap底层Hash冲突是什么?以及如何解决Hash冲突 【杭州多测师_王sir】【杭州多测师】...

news2024/11/26 18:53:17

一、hashMap的底层实现hashmap的底层结构在jdk1.7之前是数组+链表,但是在jdk1.8以后,其变成了数组+链表+红黑树,
这个操作会加快在链表时候的查询速度。
当链表的长度大于8 的时候,链表就会变为红黑树,而当长度小于6的时候,会从红黑树变回链表。
这里又有一个问题:为什么是8 和 6 这两个阈值呢?
因为TreeNodes的大小大约是常规节点的两倍,我们只在bins包含足够的节点来保证使用时才使用它们(参见TREEIFY_THRESHOLD)。
当它们变得太小(由于删除或调整大小)时,它们被转换回普通容器。 在使用分布良好的用户hashCodes时,很少使用树容器。
理想情况下,在随机hashCodes下,bin中的节点频率遵循泊松分布(http://en.wikipedia.org/wiki/Poisson_distribution),默认调整大小阈值为0.75,参数平均约为0.5,尽管由于调整粒度而存在很大的差异。
忽略方差,列表大小k的预期出现次数为(exp(-0.5) * pow(0.5, k) / factorial(k))。
0: 0.60653066
1: 0.30326533
2: 0.07581633
3: 0.01263606
4: 0.00157952
5: 0.00015795
6: 0.00001316
7: 0.00000094
8: 0.00000006
如果不设退化阀值,只以8来树化与退化: 那么8将成为一个临界值,时而树化,时而退化,此时会非常影响性能,因此,我们需要一个比8小的退化阀值;
UNTREEIFY_THRESHOLD = 7 同样,与上面的情况没有好多少,仅相差1个元素,仍旧会在链表与树之间反复转化;
那为什么是6呢? 源码中也说了,考虑到内存(树节点比普通节点内存大2倍,以及避免反复转化),所以,退化阀值最多为6。HashMap有4个构造器,其他构造器如果用户没有传入initialCapacity 和loadFactor这两个参数,会使用默认值initialCapacity(初始容量)默认为16,loadFactory默认为0.75
那么负载因子为什么是0.75 呢?
负载因子 = 1.0
负载因子为1.0时,意味着,只有当 table 全部被填满,table 才会扩容;当 table 中的元素越来越多时,会出现大量的冲突:
若此时是链表,则查询效率是 O(n),即线性;(插入/删除结点也要遍历到链表);
若此时是红黑树,查询效率是 O(logN),但红黑树的插入与删除就异常复杂,每次都要调整树;
因此,负载因子1.0,实际是牺牲了时间,但保证了空间的利用率。
负载因子 = 0.5
负载因子为0.5时,意味着,当 table 中的元素达到一半时,就发生扩容,table 容量扩大一倍:
hash 冲突减少;
链表长度不会很长;
即便链表长度超过8时转成红黑树,树的高度也不会很高;
查询效率提高了,但这里,我们发现,会有大量的内存浪费,因为数组中的个数永远小于数组长度的一半。
因此,负载因子0.5,实际是牺牲了空间,但保证了时间效率。
负载因子在【0.5 1.0】分别对应着时间极端和空间极端,为了平衡这两个极端的情况,于是就进行了中和,使用了0.75这个中间的负载因子,为了平衡时间和空间成本hashMap不是线程安全的。因为其中的方法没有使用synchronized 来修饰方法hashMap的put方法

public V put(K key, V value) {  
        if (key == null)  
            return putForNullKey(value);  
        int hash = hash(key.hashCode());  
        int i = indexFor(hash, table.length);  
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {  
            Object k;  
            //判断当前确定的索引位置是否存在相同hashcode和相同key的元素,
            //如果存在相同的hashcode和相同的key的元素,那么新值覆盖原来的旧值,并返回旧值。  
            //如果存在相同的hashcode,那么他们确定的索引位置就相同,这时判断他们的key是否相同,
            //如果不相同,这时就是产生了hash冲突。  
            //Hash冲突后,那么HashMap的单个bucket里存储的不是一个 Entry,而是一个 Entry 链。  
            //系统只能必须按顺序遍历每个 Entry,直到找到想搜索的 Entry 为止——如果恰好要搜索的Entry 
            //位于该 Entry 链的最末端(该 Entry 是最早放入该 bucket 中),  
            //那系统必须循环到最后才能找到该元素。  
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
                V oldValue = e.value;  
                e.value = value;  
                return oldValue;  
            }  
        }  
        modCount++;  
        addEntry(hash, key, value, i);  
        return null;  
    }  

二、hashMap的扩容机制

三、什么是hash冲突
根据key(键)即经过一个函数f(key)得到的结果的作为地址去存放当前的key value键值对(这个是hashmap的存值方式),但是却发现算出来的地址上已经被占用了。这就是所谓的hash冲突。四、hashMap如何解决hash冲突1)开放定址法
该方法也叫做再散列法,其基本原理是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi 。2)再Hash法
这种方法就是同时构造多个不同的哈希函数: Hi=RH1(key) i=1,2,…,k。当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。3)链地址法(Java就是采用这种方法)
其基本思想: 将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。4)建立公共溢出区
这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。

本文章学习参考以下文章:https://blog.csdn.net/jiu_mu_mu/article/details/120919564https://blog.csdn.net/abcd1430/article/details/52745155https://blog.csdn.net/weixin_42398171/article/details/112096446https://www.jianshu.com/p/a7a76c5b8435https://www.jianshu.com/p/f323f4b0c109

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

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

相关文章

培训机构的存在对 IT 行业产生了哪些影响

这个标题我一看&#xff0c;应该就会引发一波口水、键盘要遭罪啦。。。做为从业十余年&#xff0c;培训行业从事也已经快7年了。 在正厚软件从一开始到今天。从讲师到教学和团队的协作、校区运营&#xff0c;从行业小白到对整体机构的运营和团队&#xff0c;有些许经验谈下个人…

测试4年裸辞失业,面试17k的测试岗被按在地上摩擦,结局让我崩溃大哭....

作为IT行业的大热岗位——软件测试&#xff0c;只要你付出了&#xff0c;就会有回报。说它作为IT热门岗位之一是完全不虚的。可能很多人回说软件测试是吃青春饭的&#xff0c;但放眼望去&#xff0c;哪个工作不是这样的呢&#xff1f;会有哪家公司愿意养一些闲人呢&#xff1f;…

FKM规范在非焊接构件中的静强度评估方法介绍(上篇)

导读&#xff1a;FKM &#xff08;《Analytical Strength Assessment of Components in Mechanical Engineering》&#xff09;规范是德国机械工程研究委员会根据机械产品在实际工程中的应用情况&#xff0c;统计出的针对由钢、铸铁及铝材料制成构件的静强度及疲劳强度的评估规…

C++模板(第二版)笔记之第六章:移动语义和 enable_if

文章目录一、完美转发&#xff08;Perfect Forwarding&#xff09;二、特殊成员函数模板&#xff1a;构造函数三、 通过 std::enable_if<>禁用模板四、 使用 enable_if<>1.不能通过使用 enable_if<>来禁用 copy/move 构造函数以及赋值构造函数五、使用 conce…

0124 双指针 Day13

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 输入一个整数数组&#xff0c;实现一个函数来调整该数组中数字的顺序&#xff0c;使得所有奇数在数组的前半部分&#xff0c;所有偶数在数组的后半部分。 示例&#xff1a; 输入&#xff1a;nums [1,2,3,4] 输出&#xff1a…

net基于asp.net的计算机网络课程题库系统-计算机毕业设计

项目介绍 计算机网络课程题库系统是针对目前计算机网络课程试题的实际需求,从实际工作出发,对过去的计算机网络课程试题平台存在的问题进行分析,完善用户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高,节省了开支,提高了工作的效率。 本系统结…

操作系统_线程安全问题

文章目录1.线程安全问题举例2.为什么会有线程安全问题3.如何解决线程安全问题1.从原子性入手解决线程安全问题2.synchronized的使用方法3.java标准库中的线程安全类4.死锁问题举例2.死锁的必要条件1.线程安全问题举例 看代码: class Count {int i 0;public void add(){i;} }…

Sklearn机器学习与Plotly可视化强强联合

在学习sklearn(机器学习)过程中&#xff0c;模型原理可谓是枯燥无味&#xff0c;加上大多数模型训练过程也是不可见的&#xff0c;这使得很多小伙伴们望而却步&#xff0c;当然也有很多学者试图通过各种方式以可视化模型学习及预测过程&#xff0c;但大多数是复杂且不美观的。 …

Windows后台运行并启动Frpc客户端界面

Windows后台运行并启动Frpc客户端界面 frp搭建内网穿透可以看我另外一篇 1.frps服务端配置 [common] bind_port 3000 vhost_http_port 4000 vhost_https_port 5000authentication_method token authenticate_new_work_conns true token 5ae9394f-32d8-4a58-b6ed-e9f36…

【微服务技术05】Ribbon负载均衡

【微服务技术05】Ribbon负载均衡 案例代码&#xff1a;https://gitee.com/pikachu2333/spring-cloud-hexuan 之前配置好了eureka注册中心&#xff0c;使用RestTemplate调用地址为&#xff1a;http://eureka-user-service/user/1&#xff0c;配置了LoadBalanced负载均衡注解 但…

使用RTP包荷载AAC码流数据

目录 一. 前言 二. RTP协议介绍 三. AAC介绍 1. AAC格式 2. ADTS 四. RTP与AAC的结合 五. 代码实战 六. 效果展示 一. 前言 音视频通话中我们通常使用 RTP 协议包荷载音视频码率数据&#xff0c;例如麦克风采集输入数据后编码成帧&#xff0c;再将帧数据放入 RTP 协议包…

B站:以SLO为核心的可用性观测与质量运营

UGeek大咖说是优维科技为技术爱好者研讨云原生技术演进趋势而创办的系列活动&#xff0c;邀请一线互联网大厂的核心骨干主讲&#xff0c;分享原厂实践。本年度主题为可观测&#xff0c;我们希望通过一场场有趣、有料、有深度的活动&#xff0c;让运维圈的小伙伴聚集在一起&…

Java知识点--反射(上)

Java知识点--反射&#xff08;上&#xff09;&#x1f356;一、为什么需要反射1️⃣在特定情境中传统方法的不足2️⃣为了不修改原码引出反射&#x1f357;二、反射机制1️⃣Java反射机制2️⃣Java 反射机制原理示意图3️⃣Java 反射机制可以完成4️⃣反射相关的主要类5️⃣反射…

java计算机毕业设计ssm在线学习资源管理系统t4ko5(附源码、数据库)

java计算机毕业设计ssm在线学习资源管理系统t4ko5&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java丹徒高级中学校车预约9poqj

大四计算机专业的同学们即将面临大学4年的最后一次考验--毕业设计。通过完成毕业设计来对过去4年的大学学习生活做一个总结&#xff0c;也是检验我们学习成果的一种方式&#xff0c;毕业设计作品也是我们将来面试找工作的一个敲门砖。 选题前先看看自己掌握哪些技术点、擅长哪…

Denoising Diffusion Probabilistic Models

目录概要前向过程nice property逆向过程参数推导简化参考资料概要 Denoising Diffusion Probabilistic Model(DDPM)是一个生成模型&#xff0c;给定一个目标分布&#xff0c;学习模型以便可以从目标分布中采样。 使用马尔科夫链建模。输入是噪声&#xff0c;通过神经网络逐步去…

伟大的缝纫师—typedef

伟大的缝纫师—typedef一.历史的误会—也许应该是typerename二.typedef和#define的区别一.历史的误会—也许应该是typerename 为什么这样说呢&#xff1f;因为typedf其实就是一个重命名关键字&#xff0c;看示例 这里我觉得unsigned int太长了&#xff0c;我将它改名为u_int&am…

bat批处理文件的注释,和常用简单命令

参考&#xff1a;https://learn.microsoft.com/zh-cn/windows-server/administration/windows-commands/windows-commands&#xff0c;https://blog.csdn.net/wuhenyouyuyouyu/article/details/120736519? 当前路径&#xff1a;%~dp0 这个参数只能在bat文件中在正常使用&…

Unity脚本(2) --- 脚本生命周期以及脚本的控制台调试

1.什么是脚本生命周期&#xff1f; 首先什么是脚本 --- 脚本的本质其实就是类&#xff0c;而脚本生命周期其实就是脚本对应的那个类从开始工作到最后销毁这么一个周期 &#xff08;或者说是Unity脚本从唤醒到销毁的过程&#xff09; &#xff08;消息&#xff0c;必然事件&am…

[附源码]Node.js计算机毕业设计儿童成长记录与分享系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…