HashMap解决hash冲突的方法

news2024/2/27 14:53:20

HashMap解决hash冲突的方法

  • 博客分类: 
  • jvm虚拟机
 

       在Java编程语言中,最基本的结构就是两种,一种是数组,一种是模拟指针(引用),所有的数据结构都可以用这两个基本结构构造,HashMap也一样。当程序试图将多个 key-value 放入 HashMap 中时,以如下代码片段为例:

HashMap<String,Object> m=new HashMap<String,Object>(); 
m.put("a", "rrr1"); 
m.put("b", "tt9"); 
m.put("c", "tt8"); 
m.put("d", "g7"); 
m.put("e", "d6"); 
m.put("f", "d4"); 
m.put("g", "d4"); 
m.put("h", "d3"); 
m.put("i", "d2"); 
m.put("j", "d1"); 
m.put("k", "1"); 
m.put("o", "2"); 
m.put("p", "3"); 
m.put("q", "4"); 
m.put("r", "5"); 
m.put("s", "6"); 
m.put("t", "7"); 
m.put("u", "8"); 
m.put("v", "9");

        HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置。当程序执行 map.put(String,Obect)方法 时,系统将调用String的 hashCode() 方法得到其 hashCode 值——每个 Java 对象都有 hashCode() 方法,都可通过该方法获得它的 hashCode 值。得到这个对象的 hashCode 值之后,系统会根据该 hashCode 值来决定该元素的存储位置。源码如下:

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

       上面程序中用到了一个重要的内部接口:Map.Entry,每个 Map.Entry 其实就是一个 key-value 对。从上面程序中可以看出:当系统决定存储 HashMap 中的 key-value 对时,完全没有考虑 Entry 中的 value,仅仅只是根据 key 来计算并决定每个 Entry 的存储位置。这也说明了前面的结论:我们完全可以把 Map 集合中的 value 当成 key 的附属,当系统决定了 key 的存储位置之后,value 随之保存在那里即可.HashMap程序经过我改造,我故意的构造出了hash冲突现象,因为HashMap的初始大小16,但是我在hashmap里面放了超过16个元素,并且我屏蔽了它的resize()方法。不让它去扩容。这时HashMap的底层数组Entry[]   table结构如下: 

   

       Hashmap里面的bucket出现了单链表的形式,散列表要解决的一个问题就是散列值的冲突问题,通常是两种方法:链表法和开放地址法。链表法就是将相同hash值的对象组织成一个链表放在hash值对应的槽位;开放地址法是通过一个探测算法,当某个槽位已经被占据的情况下继续查找下一个可以使用的槽位。java.util.HashMap采用的链表法的方式,链表是单向链表。形成单链表的核心代码如下:

 

Java代码   收藏代码
  1. void addEntry(int hash, K key, V value, int bucketIndex) {  
  2.     Entry<K,V> e = table[bucketIndex];  
  3.     table[bucketIndex] = new Entry<K,V>(hash, key, value, e);  
  4.     if (size++ >= threshold)  
  5.         resize(2 * table.length);  
  6. bsp;  

     上面方法的代码很简单,但其中包含了一个设计:系统总是将新添加的 Entry 对象放入 table 数组的 bucketIndex 索引处——如果 bucketIndex 索引处已经有了一个 Entry 对象,那新添加的 Entry 对象指向原有的 Entry 对象(产生一个 Entry 链),如果 bucketIndex 索引处没有 Entry 对象,也就是上面程序代码的 e 变量是 null,也就是新放入的 Entry 对象指向 null,也就是没有产生 Entry 链。

       HashMap里面没有出现hash冲突时,没有形成单链表时,hashmap查找元素很快,get()方法能够直接定位到元素,但是出现单链表后,单个bucket 里存储的不是一个 Entry,而是一个 Entry 链,系统只能必须按顺序遍历每个 Entry,直到找到想搜索的 Entry 为止——如果恰好要搜索的 Entry 位于该 Entry 链的最末端(该 Entry 是最早放入该 bucket 中),那系统必须循环到最后才能找到该元素。

       当创建 HashMap 时,有一个默认的负载因子(load factor),其默认值为 0.75,这是时间和空间成本上一种折衷:增大负载因子可以减少 Hash 表(就是那个 Entry 数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的的操作(HashMap 的 get() 与 put() 方法都要用到查询);减小负载因子会提高数据查询的性能,但会增加 Hash 表所占用的内存空间。

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

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

相关文章

快速理解平衡二叉树、B-tree、B+tree、B*tree

原文:https://my.oschina.net/u/3370829/blog/1301732 觉得这篇文章比较好,特此分享 1、平衡二叉树 (1)由来:平衡二叉树是基于二分法的策略提高数据的查找速度的二叉树的数据结构; (2)特点: 平衡二叉树是采用二分法思维把数据按规则组装成一个树形结构的数据,用…

android popupwindow dialog区别,Android PopUpWindow使用详解

释放双眼&#xff0c;带上耳机&#xff0c;听听看~&#xff01;一、概述1、PopupWindow与AlertDialog的区别最关键的区别是AlertDialog不能指定显示位置&#xff0c;只能默认显示在屏幕最中间(当然也可以通过设置WindowManager参数来改变位置)。而PopupWindow是可以指定显示位置…

深入浅出K-Means算法

深入浅出K-Means算法 摘要&#xff1a;在数据挖掘中&#xff0c;K-Means算法是一种 cluster analysis 的算法&#xff0c;其主要是来计算数据聚集的算法&#xff0c;主要通过不断地取离种子点最近均值的算法。在数据挖掘中&#xff0c;K-Means算法是一种cluster analysis的算法…

kmeans算法原理以及实践操作

原文&#xff1a;http://www.cnblogs.com/dudumiaomiao/p/5839905.html kmeans算法原理以及实践操作(多种k值确定以及如何选取初始点方法) kmeans一般在数据分析前期使用&#xff0c;选取适当的k&#xff0c;将数据聚类后&#xff0c;然后研究不同聚类下数据的特点。 算法原理&…

define 双引号 其他宏_当年宏语言不受欢迎?背后的原因你知道吗?

人类用计算机处理文本主要是依赖宏语言以及一些专用的文本编辑器。事实上&#xff0c;早期的文本编辑器只提供基本的文本编辑功能&#xff0c;然后借助宏语言进行功能扩展。结果人类很快就发现&#xff0c;基于宏扩展的编辑器&#xff0c;功能越复杂&#xff0c;它的行为就越诡…

K-means聚类算法的三种改进(K-means++,ISODATA,Kernel K-means)介绍与对比

原文&#xff1a;http://www.cnblogs.com/yixuan-xu/p/6272208.html K-means聚类算法的三种改进(K-means,ISODATA,Kernel K-means)介绍与对比 一、概述 在本篇文章中将对四种聚类算法(K-means,K-means,ISODATA和Kernel K-means)进行详细介绍&#xff0c;并利用数据集来真实地反…

数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

原文&#xff1a;http://blog.csdn.net/sup_heaven/article/details/39313731 数据结构中常见的树&#xff08;BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B树、B*树&#xff09; 转载 2014年09月16日 12:07:0827624 BST树 即二叉搜索树&#xff1a; 1.所有非叶子结点至…

html载入字体,css怎么导入字体?

在做前端页面的时候&#xff0c;有些内容文字需要通过css来指定第三方的字体进行显示&#xff0c;而不是默认支持的一些字体&#xff0c;这就需要自己制作或者获得字体文件&#xff0c;然后放入对应的字体目录&#xff0c;并通过font-family来指定字体。在 CSS3 之前&#xff0…

奇异值的物理意义

知乎上的解释特别好&#xff0c;非常佩服&#xff0c;在此转载一下&#xff0c;做个笔记 原文&#xff1a;https://www.zhihu.com/question/22237507/answer/28007137 奇异值作用&#xff1a;图片压缩&#xff0c;去燥&#xff0c;模糊等等矩阵的奇异值是一个数学意义上的概念…

mabatisplus怎么给实体类自定义属性_如果你的角色属性可以自定义,你会怎么点?...

如今越来越多的人抱怨小时候学的一些特长&#xff0c;长大之后根本没什么用处&#xff0c;比如乐器、绘画等等。反而是一些实用的比如烹饪和动手能力更受到大家的欢迎。阿庆想说的是&#xff0c;你肯定是没有坚持&#xff0c;到最后自然只能像方仲永一样“泯然众人矣”了。在游…

selector多路复用_超详细的I/O多路复用概念、常用I/O模型、系统调用等介绍

概述当我们要编写一个echo服务器程序的时候&#xff0c;需要对用户从标准输入键入的交互命令做出响应。在这种情况下&#xff0c;服务器必须响应两个相互独立的I/O事件&#xff1a;1)网络客户端发起网络连接请求&#xff0c;2)用户在键盘上键入命令行。我们先等待哪个事件呢&am…

余弦计算相似度度量

目录 pytorch 余弦相似度&#xff0c; 余弦计算相似度度量 pytorch 余弦相似度&#xff0c; 余弦相似度1到-1之间&#xff0c;1代表正相关&#xff0c;0代表不相关&#xff0c;-1代表负相关 def l2_norm(input, axis1):norm torch.norm(input, 2, axis, True)output torc…

程序员表白简短html代码,【杂谈】2018浪漫七夕:7款程序员必备表白源码(超炫酷)...

2018七夕将要来临&#xff0c;ki4网给大家准备了七款程序员表白专用源码&#xff0c;让你可以一举俘获美人心&#xff0c;下面就来看一看这七款表白代码大全&#xff0c;包含html、html5、CSS、JQ编写的一些非常简单实用的表白代码&#xff0c;非常炫酷、浪漫&#xff01;1、CS…

哪种css实现方式优势更突出_【第十三课】更合理的CSS结构

前言从零开始学前端系列课程&#xff0c;与传统的视频大课堂教学不同&#xff0c;没有填鸭&#xff1b;也普通做练习题的方式不同&#xff0c;没有假想的模拟题。 本课程拆出80个左右必须掌握的技能点&#xff0c;并对其分组&#xff0c;从易到难地列出学习曲线。同时从真实项目…

TF-IDF与余弦相似性的应用

原文&#xff1a;http://www.ruanyifeng.com/blog/2013/03/tf-idf.html TF-IDF与余弦相似性的应用&#xff08;一&#xff09;&#xff1a;自动提取关键词 这个标题看上去好像很复杂&#xff0c;其实我要谈的是一个很简单的问题。 有一篇很长的文章&#xff0c;我要用计算机提取…

webloigc12服务启动不了_一键启动知多少!

一键启动(自动挡车型)相比对手动挡的钥匙启动高大上不会出现膝盖被钥匙磕到的情况也不会出现钥匙孔边上有划痕的现象但是一键启动开关启动的顺序是什么&#xff1f;是长按至启动还是通电后再启动&#xff1f;一键启动常见问题答疑■ 问&#xff1a;一键启动车辆是如何启动的&a…

机器学习算法之决策树

原文&#xff1a;http://www.jianshu.com/p/6eecdeee5012 决策树是一种简单高效并且具有强解释性的模型&#xff0c;广泛应用于数据分析领域。其本质是一颗由多个判断节点组成的树&#xff0c;如&#xff1a; 决策树在使用模型进行预测时&#xff0c;根据输入参数依次在各个判断…

组件三层_Angular 练级之旅(8)-Zorro Select组件的实现和进阶

很久没写相关的文章&#xff0c;正好前两天把抄来的Select组件重写了一下&#xff0c;简化了一些逻辑。先看下zorro 中select组件的一个目录结构zorro将select组件分成了 三大块Input / 选择框下拉列表连接以上2层的控制器层先看 我们使用的 nz-select 内部的模板到底是什么样的…

目标检测 RCNN算法详解

原文&#xff1a;http://blog.csdn.net/shenxiaolu1984/article/details/51066975 【目标检测】RCNN算法详解 Girshick, Ross, et al. “Rich feature hierarchies for accurate object detection and semantic segmentation.” Proceedings of the IEEE conference on comput…

燕赵志愿云如何认证_如何获得云安全专家CCSP认证

关注↑↑↑我们获得更多精彩内容&#xff01;千呼万唤始出来&#xff0c;云安全专家CCSP认证正式上线&#xff0c;全文皆重点&#xff0c;请仔细查看。CCSP云安全专家认证是什么&#xff1f;两家国际顶尖的安全组织,云安全联盟Cloud Security Alliance与 (ISC)&#xff0c;在20…