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.
@Override
public int hashCode() {
if (this.name.length() % 2 == 0)
return 31;
else
return 95;
}
@Override
public 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 line
while (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进行链接。

HashMap的hash冲突解决方案的更多相关文章

  1. HashMap解决hash冲突的方法

    HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置.当程序执行 map.put(String,Obect)方法 时,系统将调用String的 hashCode() 方法得到其 h ...

  2. Map之HashMap的get与put流程,及hash冲突解决方式

    在java中HashMap作为一种Map的实现,在程序中我们经常会用到,在此记录下其中get与put的执行过程,以及其hash冲突的解决方式: HashMap在存储数据的时候是key-value的键值 ...

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

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

  4. HashMap的内部结构与hash冲突

    HashMap的内部结构 HashMap简介: HashMap继承AbstractMap,AbstractMap实现Map接口 HashMap是线程不同步的,线程不安全的 HashMap可以把null ...

  5. hashMap 源码解读理解实现原理和hash冲突

    hashMap 怎么说呢. 我的理解是 外表是一个set 数组,无序不重复 . 每个set元素是一个bean ,存着一对key value 看看代码吧 package test; import jav ...

  6. JDK8;HashMap:再散列解决hash冲突 ,源码分析和分析思路

    JDK8中的HashMap相对JDK7中的HashMap做了些优化. 接下来先通过官方的英文注释探究新HashMap的散列怎么实现 先不给源码,因为直接看源码肯定会晕,那么我们先从简单的概念先讲起   ...

  7. 大厂面试必问!HashMap 怎样解决hash冲突?

    HashMap冲突解决方法比较考验一个开发者解决问题的能力. 下文给出HashMap冲突的解决方法以及原理分析,无论是在面试问答或者实际使用中,应该都会有所帮助. 在Java编程语言中,最基本的结构就 ...

  8. HashMap的hash分析

    哈希 Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空 ...

  9. 没想到 Hash 冲突还能这么玩,你的服务中招了吗?

    背景 其实这个问题我之前也看到过,刚好在前几天,洪教授在某个群里分享的一个<一些有意思的攻击手段.pdf>,我觉得这个话题还是有不少人不清楚的,今天我就准备来“实战”一把,还请各位看官轻拍 ...

随机推荐

  1. Ubuntu-14.04.1 desktop安装时及安装后遇到的小问题

    ubuntu安装时,进入桌面就黑屏:ctrl+alt+F1进入终端1,输入:startx,此时桌面会重新出现,快速修改桌面的分辨率即可.没有及时修改可以重复上面操作. su root认证失败:sudo ...

  2. 学习MongoDB 二:MongoDB添加、删除、修改

    一.简介 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSQL数据库产品中最热门的一种.数据被分组存储在数据集中,被称为一个集合(Collenction)和对于存储在MongoDB ...

  3. 手机app/h5页面http请求抓包调试

    1.抓包机器跟客户端手机连上同一wifi热点,最好是第三者提供的移动wifi,公司内网wifi网络访问有限制. 2.设置手机客户端http代理 三者关系图示:

  4. ckeditor源码编辑模式,添加style、javascript内容丢失的解决

    我使用ckeditor 我在编辑的使用源码编辑,保存内容包含javascript.style标签的时候,数据库中有javascript.style标签 , 输入到页面也可以执行,但是我再次编辑的时候就 ...

  5. smyfony2-curd-数据库创建

    1创建类

  6. XMind8 安装

    参考:https://blog.csdn.net/qq_35911589/article/details/81901868 https://blog.csdn.net/Zjhao666/article ...

  7. HTML5 Canvas ( 图片填充样式 ) fillStyle, createPattern

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. HTML5拖动

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  9. python常见异常提示

    PEP8 expected 2 blank lines, found 1 定义方法时,出现期望是2个空白行,但是实际检测到是1个.方法与上面内容间隔期望为两个换行符 PEP8 This diction ...

  10. EL&jsp

    JSP 2.0(java server pages): EL 表达式 JSP九大内置对象及作用范围 JSP Directive JSP Action EL表达式: EL 算法(Arithmetic)表 ...