Hash函数

  非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的关系,查找的过程为给定值一次和各个关键字进行比较,查找的效率取决于和给定值进行比较的次数。

哈希表的特点:关键字在表中位置和它之间存在一种确定的关系。

  哈希函数:一般情况下,需要在关键字与它在表中的存储位置之间建立一个函数关系,以f(key)作为关键字为key的记录在表中的位置,通常称这个函数f(key)为哈希函数。

hash : 翻译为“散列”,就是把任意长度的输入,通过散列算法,变成固定长度的输出,该输出就是散列值。

这种转换是一种压缩映射,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值。

简单的说就是一种将任意长度的消息压缩到莫伊固定长度的消息摘要的函数。

hash冲突:就是根据key即经过一个函数f(key)得到的结果的作为地址去存放当前的key value键值对(这个是hashmap的存值方式),但是却发现算出来的地址上已经有人先来了。就是说这个地方被抢了啦。这就是所谓的hash冲突啦。

哈希函数处理冲突的方法

  1.开放定址法:

              

    其中 m 为表的长度

    对增量di有三种取法:

    线性探测再散列   di = 1 , 2 , 3 , ... , m-1

    平方探测再散列   di = 1 2 , -2 , 4 , -4 , 8 , -8 , ... , k的平方 ,  -k平方

    随机探测再散列   di 是一组伪随机数列

            

  2.链地址法

   这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

             

  3.再哈希

    这种方法是同时构造多个不同的哈希函数:

  Hi=RH1(key)  i=1,2,…,k

  当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。

  4.建立公共溢出区

这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表

HashMap的Hash冲突处理办法

  hashmap出现了Hash冲突的时候采用第二种办法:链地址法。

代码示例:

  有一个”国家”(Country)类,我们将要用Country对象作为key,它的首都的名字(String类型)作为value。下面的例子有助于我们理解key-value对在HashMap中是如何存储的。

public class Country {String name;long population;public Country(String name, long population) {super();this.name = name;this.population = population;}public String getName() {return name;}public void setName(String name) {this.name = name;}public long getPopulation() {return population;}public void setPopulation(long population) {this.population = population;}// If length of name in country object is even then return 31(any random// number) and if odd then return 95(any random number).// This is not a good practice to generate hashcode as below method but I am// doing so to give better and easy understanding of hashmap.
    @Overridepublic int hashCode() {if (this.name.length() % 2 == 0)return 31;elsereturn 95;}@Overridepublic boolean equals(Object obj) {Country other = (Country) obj;if (name.equalsIgnoreCase((other.name)))return true;return false;}}

public class HashMapStructure {public static void main(String[] args) {Country india = new Country("India", 1000);Country japan = new Country("Japan", 10000);Country france = new Country("France", 2000);Country russia = new Country("Russia", 20000);HashMap<Country, String> countryCapitalMap = new HashMap<Country, String>();countryCapitalMap.put(india, "Delhi");countryCapitalMap.put(japan, "Tokyo");countryCapitalMap.put(france, "Paris");countryCapitalMap.put(russia, "Moscow");Iterator<Country> countryCapitalIter = countryCapitalMap.keySet().iterator();// put debug point at this linewhile (countryCapitalIter.hasNext()) {Country countryObj = countryCapitalIter.next();String capital = countryCapitalMap.get(countryObj);System.out.println(countryObj.getName() + "----" + capital);}}}

  在注释处加入debug,可以通过watch查看countryCapitalMap的结构:

          

从上图可以观察到以下几点:

  1. 有一个叫做table大小是16的Entry数组。

  2. 这个table数组存储了Entry类的对象。HashMap类有一个叫做Entry的内部类。这个Entry类包含了key-value作为实例变量。我们来看下Entry类的结构。Entry类的结构: 

static class Entry implements Map.Entry{final K key;V value;Entry next;final int hash;...//More code goes here
} 

    1).每当往hashmap里面存放key-value对的时候,都会为它们实例化一个Entry对象,这个Entry对象就会存储在前面提到的Entry数  组table中。现在你一定很想知道,上面创建的Entry对象将会存放在具体哪个位置(在table中的精确位置)。答案就是,根据key的     hashcode()方法计算出来的hash值(来决定)。hash值用来计算key在Entry数组的索引。

    2).现在,如果你看下上图中数组的索引15,它有一个叫做HashMap$Entry的Entry对象。

    3).我们往hashmap放了4个key-value对,但是看上去好像只有1个元素!!!这是因为,如果两个元素有相同的hashcode,它们会  被放在同一个索引上。问题出现了,该怎么放呢?原来它是以链表(LinkedList)的形式来存储的(逻辑上)。因此他们都在hash值为15的位置  上存着了,然后把多个Entry,用next进行链接。

转载于:https://www.cnblogs.com/jing99/p/6985618.html

HashMap的hash冲突解决方案相关推荐

  1. HashMap解决hash冲突的方法

    HashMap解决hash冲突的方法 博客分类: jvm虚拟机 在Java编程语言中,最基本的结构就是两种,一种是数组,一种是模拟指针(引用),所有的数据结构都可以用这两个基本结构构造,HashMap ...

  2. HashMap 中 hash 冲突的解决方法及原理分析

    我们最先衰老的不是容貌,而是不顾一切的闯劲.有时候,要敢于背上超出自己预料的包袱,真的努力后,你会发现自己要比想象的优秀很多. HashMap冲突的解决方法比较考验一个开发者解决问题的能力. 在Jav ...

  3. Hashmap解决hash冲突为什么使用红黑树

    首先,在解决这个问题之前我们要先了解hash冲突是什么. hash冲突 hashmap在添加新的键值对的时候,会根据key值通过一个函数计算出一个结果作为地址值,根据这个地址值将其键值对插入到对应的位 ...

  4. HashMap解决Hash冲突为什么要使用红黑树

    1.HashMap的数据结构 HashMap是由数组与链表来实现的,同时,也具备了数组和链表的所以特点 2.什么是hash冲突 hash冲突:就是根据key即经过一个哈希变换得到的结果的作为地址去存放 ...

  5. 1.Hashmap 解决hash冲突为什么使用红黑树

    1.  hash冲突指的是在向Hash表中存数据时,首先要用Hash函数计算出该数据要存放的地址.但是在这个地址中已经有值存在,所以这个时候就发生了Hash冲突.也就是说:值不同的元素可能会映象到哈希 ...

  6. hashmap hash冲突怎么解决_HashMap原理

    HashMap的问题,在现在的技术面试中,基本上都会问到,而且这个集合在开发中也会经常使用到,希望通过本文能有所收获. 一.问题分析 1.HashMap的底层数据结构是什么? 2.HashMap中CR ...

  7. 分析Threadlocal内部实现原理,并解决Threadlocal的ThreadLocalMap的hash冲突与内存泄露

    前言 ThreadLocal 的经典使用场景是数据库连接. session 管理.多线程等-- 比如在Spring中,发挥着巨大的作用,在管理Request作用域中的Bean.事务管理.任务调度.AO ...

  8. HashMap之Hash碰撞冲突解决方案及未来改进

    说明:参考网上的两篇文章做了简单的总结,以备后查(http://blogread.cn/it/article/7191?f=wb  ,http://it.deepinmind.com/%E6%80%A ...

  9. hashMap怎么解决hash冲突的

    2019独角兽企业重金招聘Python工程师标准>>> 学Java的都知道hashMap的底层是"链表散列"的数据结构也也可以说是hash表.在put的实话先根据 ...

最新文章

  1. Nat. Med. | 人工智能临床研究新指南
  2. 微软亚洲研究院副院长刘铁岩:以计算之矛攻新冠之盾
  3. Digital Signage and Windows Embedded Standard 7
  4. linux存储--inode与block详解(七)
  5. python读取文件如何去除空格_python读取txt文件时怎么去掉空格
  6. java备还原mysql_用java来备份还原mysql数据库
  7. The Triangle
  8. 7-24 树种统计 (25 分)(详解)map做法 map真香啊!
  9. 一文彻底看懂成交量的本质
  10. [ajaxpro] ajax效果可以实现但是报错,还经常使ie假死的问题解决
  11. Linux入门学习(二) —— 怎么创建文件?怎么复制、剪切、删除文件?
  12. WordPress SEO 技巧
  13. 【设计模式】-状态模式->APP抽奖活动(源码与类图解析)
  14. 2021 百度网盘网页版 倍速播放技巧(亲测有效)
  15. 护眼台灯真的护眼吗?为家长推荐四款真正护眼的台灯
  16. 【顺序表】13 顺序表ADT模板设计及简单应用:将顺序表中前 m 个元素和后 n 个元素进行互换
  17. 场内场外交易成本_什么是场内交易与场外交易?有何区别?
  18. 学计算机励志名言,程序员励志格言
  19. 产品经理的金字塔之旅---将“打杂”的实习经历描述的高大上!!!
  20. C#使用Emgu实现大图找图,并获得匹配区域

热门文章

  1. 前端性能的几个基础指标
  2. 趣味Python入门(一):初识Python
  3. thinkphp模版调用函数方法
  4. POJ 3723 Conscription 最小生成树
  5. bnpparibas
  6. 我希望你能精简一些东西
  7. Trie 树——搜索关键词提示 1
  8. 解决Minikube start卡住的方法
  9. HTML里的哪一部分Javascript 会在页面加载的时候被执行?
  10. 基于vue-cli配置手淘的lib-flexible + rem,实现移动端自适应