您好、欢迎来到现金彩票网!
当前位置:2019全年免费资料大全 > 桶链算法 >

主流的hash算法概述及在JDK Map中的应用

发布时间:2019-06-19 04:50 来源:未知 编辑:admin

  Java中的Map实际是一个“散列表”的数据结构,散列表是逻辑上由一系列可存放词条(或其引用)的单元组成,故这些单元也称作桶(bucket) —— 一般都使用线性表来实现。

  一组词条在散列表内部的具体分布,取决于所谓的散列(hashing)方案:事先在词条与桶地址之间约定的某种映射关系,可描述为从关键码空间到桶数组地址空间的函数: hash() 。

  址(hashing address),亦即与关键码key相对应的桶在散列表中的位置。

  所有散列函数都有如下一个基本特性:根据同一散列函数计算出的散列值如果不同,那么输入值肯定也不同。但是,根据同一散列函数计算出的散列值如果相同,输入值不一定相同。对于java而言即如果 hashcode方法返回相同,equals方法不一样返回相同。但equals方法返回相同,则hashcode必须相同。

  最佳的情况是充分利用有限的散列表空间,即散列函数最好是满射(定义域R与散列表的单元一一对应)。

  当然,因定义域规模R远远大于散列表空间规模,散列函数不可能是单射。这就意味着,关键码不同的词条被映射到同一散列地址的情况称作散列冲突(collision)。

  将散列表长度M取作为素数(只有为素数才能让其分布更加均匀,并将关键码key映射至key关于M整除的余数: hash(key) = key % M

  除余法的劣势:残留有某种连续性。相邻关键码所对应的散列地址,总是彼此 相邻;极小的关键码,通常都被集中映射到散列表的起始区段。而0其散列地址总是0,而与散列表长度无关为弥补这一不足,可采用所谓的MAD法将关键码key映射为:

  尽管运算量略有增加,但只要常数a和b选取得当,MAD法可以很好地克服除余法原有的连续 性缺陷。除余法,也可以看做是MAD法取a = 1和b = 0的特殊情况。

  从关键码key特定进制的展开中抽取出特定的若干位,构成一个整型地址。比如,若取十进制展开中的奇数位: hash(123456789) = 13579

  当然,为保证上述函数取值落在合法的散列地址空间以内,通常都还需要对散列表长度M再

  衡量一个哈希函数的好坏的重要指标就是发生碰撞的概率以及发生碰撞的解决方案。无论散列函数设计得如何巧妙,也不可能保证不同的关键码之间互不冲突。常见的解决碰撞的方法有以下几种:

  最直截了当的一种对策是,将彼此冲突的每一组词条组织为一个线性表,分别存放于它们共同对应的桶单元中。

  各桶内相互冲突的词条串接成一个列表,故命名为separate chaining

  在原散列表之外另设一个词典结构Doverflow,一旦在插入词条时发生冲突就将该词条转存至Doverflow中。

  Doverflow相当于一个存放冲突词条的公共缓冲池,该方法也因此得名。此时的散列表也可理解为是一种递归形式的散列表。

  尽管就逻辑结构而言,独立链等策略便捷而紧凑,但绝非上策。比如,因需要引入次级关联 结构,实现相关算法的代码自身的复杂程度和出错概率都将加大大增加。反过来,因不能保证物 理上的关联性,对于稍大规模的词条集,查找过程中将需做更多的I/O操作。

  实际上,仅仅依靠基本的散列表结构,且就地排解冲突,反而是更好的选择。也就是说,若 新词条与已有词条冲突,则只允许在散列表内部为其寻找另一空桶。如此,各桶并非注定只能存 放特定的一组词条;从理论上讲,每个桶单元都有可能存放任一词条。因为散列地址空间对所有词条开放,故这一新的策略亦称作开放定址(open addressing);同时,因可用的散列地址仅限于散列表所覆盖的范围之内,故亦称作闭散列(closed hashing)。

  开放定址策略最基本的一种形式是:在插 入关键码key时,若发现桶单元ht[hash(key)]已被占用,则 转而试探桶单元ht[hash(key) + 1];若ht[hash(key) + 1] 也被占用,则继续试探ht[hash(key) + 2];…;如此不断, 直到发现一个可用空桶。当然,为确保桶地址的合法,最后还 需统一对M取模。因此准确地,第i次试探的桶单元应为:

  如此,被试探的桶单元在物理空间上依次连贯,其地址构成等差数列,该方法由此得名。

  线性试探法虽然简明紧凑,但各查找链均由物理地址连续的桶单元组成,因而会加剧关键码的聚集趋势。

  MAD法,可在一定程度上缓解上述聚集现象。而平方试探法,则是更为有效的一种方法。

  hash方法的功能是根据Key来定位这个K-V在链表数组中的位置的。也就是hash方法的输入应该是个Object类型的Key,输出应该是个int类型的数组下标。

  调用Object对象的hashCode()方法,该方法会返回一个整数,然后用这个数对HashMap或者HashTable的容量进行取模就行了。没错,其实基本原理就是这个,只不过,在具体实现上,由两个方法int hash(Object k)和int indexFor(int h, int length)来实现。但是考虑到效率等问题,HashMap的实现会稍微复杂一点。

  hash(Object k) :该方法主要是将Object转换成一个整型,该方法有一些列复杂的位运算即对hashCode进行扰动计算。目的是防止不同hashCode的高位不同但低位相同导致的hash冲突。

  位运算(&)效率要比代替取模运算(%)高很多,主要原因是位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快。以及解决负数的问题 2^n – 1 的最高位一定是0,得到的结果一定是个正数

  所以exFor 使用了 & 。并且默认长度(一定是个偶数)为2^4 = 16 ,每次扩容*2后也一定是个偶数。

  hashTable的定址,在解决的key的负数问题后直接对长度取模。对奇数取模使得其分布更加均匀(详见:。

  ConcurrentHashMap与HashMap区别不大,都是通过位运算代替取模,然后再对hashcode进行扰动(防止不同hashCode的高位不同但低位相同导致的hash冲突。)。区别在于,ConcurrentHashMap 使用了一种变种的Wang/Jenkins 哈希算法,其主要母的也是为了把高位和低位组合在一起,避免发生冲突。

  HashMap和其他基于map的类都是通过链地址法解决冲突,它们使用单向链表来存储相同索引值的元素。在最坏的情况下,这种方式会将HashMap的get方法的性能从O(1)降低到O(n)。为了解决在频繁冲突时hashmap性能降低的问题,Java 8中使用平衡树来替代链表存储冲突的元素。这意味着我们可以将最坏情况下的性能从O(n)提高到O(logn)。

  如果恶意程序知道我们用的是Hash算法,则在纯链表情况下,它能够发送大量请求导致哈希碰撞,然后不停访问这些key导致HashMap忙于进行线性查找,最终陷入瘫痪,即形成了拒绝服务攻击(DoS)。

  DK1.8中的HashMap 除了将hash冲突的元素再达到8时,将该长度为8的链表转为红黑树之外,还优化了高位运算的算法(即前面提到的扰动计算)

  而JDK1.8 中的ConcurrentHashMap 并未在哈希值的计算上做过多设计,只是将Key的hashCode值与其高16位作异或并保证最高位为0(一定保证为正数值)。作者认为红黑树的效率足够高了,没必要太在意hash碰撞的问题了。

  计算理论中,没有Hash函数的说法,只有单向函数的说法。所谓的单向函数,是一个复杂的定义,大家可以去看计算理论或者密码学方面的数据。用“人类”的语言描述单向函数就是:如果某个函数在给定输入的时候,很容...博文来自:Think

  Hash是什么,它的作用先举个例子。我们每个活在世上的人,为了能够参与各种社会活动,都需要一个用于识别自己的标志。也许你觉得名字或是身份证就足以代表你这个人,但是这种代表性非常脆弱,因为重名的人很多,...博文来自:asdzheng的专栏

  JAVA中常用的数据结构(java.util.中)java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这...博文来自:u010947402的博客

  若想提高编程水平,一种方式就是看优秀框架的源码,JDK的源码就是一个很好例子,顺便也熟悉一下经常用到的类。在了解过程中,可以了解其框架设计方式,为什么要这样设计。先看看list的UML类图:...博文来自:探索java技术、web技术

  问题:要解析用户输入的字符串,如new,edit,line,load,generator等等,在软件中是否已经定义了这些字符串呢。通常的做法是将软件已经把这些字符串存在一个数组里,用户输出的字符串,与...博文来自:ucas_123的博客

  一.概念哈希表就是一种以键-值(key-indexed)存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值。哈希的思路很简单,如果所有的键都是整数,那么就可以使用一个简单的无序数组来...博文来自:liyanan21的博客

  我们下面引用一段文字来解释什么是哈希算法:哈希是一种加密算法哈希函数(HashFunction),也称为散列函数或杂凑函数。哈希函数是一个公开函数,可以将任意长度的消息M映射成为一个长度较短且长度固定...博文来自:luoye4321的专栏

  一、概述在日常的数据库操作中,我们很经常用到如下操作:selectt1.*,t2.*fromt1,t2wheret1.id=t2.id这是一个显式的表连接操作,目的就是关联2张表,取出主键能够相互...博文来自:jlr_6的专栏

  Jenkinshash算法,memcached使用了此算法Jenkinshash,可能是目前能看到的最好的hash算法之一,可以产生很好的分布,缺点是相比其他常见的hash算法更耗时。可以考虑用于ha...博文来自:chmuggmwtg的专栏

  最早,BobJenkins提出了多个基于字符串通用Hash算法(搜JenkinsHash就知道了),而ThomasWang在Jenkins的基础上,针对固定整数输入做了相应的Hash算法。其64位版本...博文来自:开心一刻的专栏

  回顾首先来回顾一下这些运算:-&(与运算):只有当两方都为true时,结果才是true,否则为false。-(或运算):只要当一方为true时,结果就是true,否则为false。-^(异或运算):...博文来自:Airsaid

  一、概述我们知道在HashMap中,一个键值对存储在HashMap内部数据的哪个位置上和K的hashCode值有关,这也是因为HashMap的hash算法要基于hashCode值来进行。这里要注意区分...博文来自:老艮头的后知后觉

  2018-05-16信通院周洁区块链技术演进及相关知识产权态势分析2018年4月20日,中国信通院、IPRdaily和纳什空间在北辰世纪中心的纳什空间联合主办了“区块链技术创新与应用闭门峰会暨“区块链...博文来自:weixin_34082177的博客

  数据结构接口及实现数据结构其实就是规定数据以何种形式存储,例如以队列的形式、以散列表的形式,还是以树的形式或者以图的形式。每一种存储方式都有不同的优势,因为每一种结构存储不同类型的数据,只要选择好相应...博文来自:煦风云海博客

  访问者模式(Visitor)访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若...博文来自:qqqqq1993qqqqq的博客

  在java中可能很多人都会忽略数据结构(类似树,跳跃表等),大家都比较熟悉链表,数组,栈,队列,哈希表等。最近看了jdk中关于树和跳跃表等的实现,其实数据结构真的是基础,有兴趣的java程序员可以翻开...博文来自:程序员之路

  前言:当被问到请举个能体现HASH算法的例子时,脑海中瞬间闪过无数个:what!哈希算法?我只隐约记得hash函数、解决冲突的方法,从何蹦出来个hash算法呢?好吧,肯定是由于自己的才疏学浅、理解能力...博文来自:TimidKid的专栏

  第一部分:TopK算法详解Hash,一般翻译做“散列”,也有直接音译为哈希的,就是把任意长度的输入(又叫做 预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这 ...博文来自:不精通则死

  一.前言MVC不是框架而是一种设计模式。MVC的全名ModelViewController,即模型-视图-控制器的缩写,这是一种设计模式,而非架构。MVC它强制的使用应用程序的输入、处理、和输...博文来自:习惯沉淀的专栏

  一、优势:#去中心化,低成本》分布式程序无需中央服务器#记录基本不可更改》区块链上的信息经由其他节点校验,当大多数节点都承认其正确性,则不可更改#可信任,去除第三方》网络中的所有节点都有机会参加校验#...博文来自:weixin_41004521的博客

  排序插入排序归并排序堆排序快速排序数据结构哈希表二叉查找树红黑树高级设计与分析技术动态规划贪心算法高级数据结构B树斐波那契堆vanemdeboas树图算法...博文来自:asivy的专栏

  JDK1.7及之前的版本中,HashMap中通过**散列链表**的形式来存储数据,基于一个数组及多个链表的方式,当hash值冲突的时候,就会在对应的节点以链表的形式存储这些hash值冲突的数据!从上面...博文来自:crazy_jack

  在项目中,同一段代码在同事的电脑上,和我的电脑上运行的结果不同,部署到tomcat中,网页显示结果为如下:在同事电脑上运行显示结果为:在我的电脑上运行显示结果为:F12查看网页的响应,发现返回的相关数...博文来自:yefengzhichen的博客

  二分查找算法是在一个有序(升序)的数据集中以集合里位于中间位置的值为基准来与要查找的值做比较,如此则把集合分为了两部分,一部分是从集合的起始位置到中间位置的前一个位置,所有的值都比中间位置的值小,另外...博文来自:hugh282003的专栏

  本文旨在分析排序算法在jdk源码中的应用,重点对java的集合排序实现进行探究,内容不会面面俱到,侧重整体结构性的分析以及部分笔者研读时受到启发的地方,希望能起到抛砖引玉的作用。序排序是一个很常用算法...博文来自:java_student09的专栏

  hash函数,即散列函数,或叫哈希函数。它可以将不定长的输入转变成定长的输出。在Java的HashMap中,是如何利用hash函数来计算index的,又是如何解决冲突的问题?本文将为你一一介绍。...博文来自:得一

  高级语言的运行机制计算机高级语言按程序的执行方式可以分为编译型和解释型两种。1.编译型语言是指使用专门的编译器,针对特定的操作系统将某种高级语言源代码一次性“翻译”成可被该平台硬件执行的机器码并包装成...博文来自:小树不倒我不倒

  最近在学习设计模式,被大家经常提及的应该就是工厂模式了,查阅了相关资料,发现之前理解的工厂模式其实是只是简单工厂模式,在正式介绍设计模式中的工厂模式之前,这篇博客先对简单工厂模式做了介绍。简单工厂模式...博文来自:Daz_M的博客

  文章目录工厂模式的应用场景未应用工厂模式工厂模式处理方案一工厂模式的应用场景需求场景:现需计划开发一个支付功能模块,初步有微信支付与支付宝支付,但随着后续业务的发展,不排除有新的支付方式。未应用工厂模...博文来自:点缀星空

  首先将高16位无符号右移16位与低十六位做异或运算。如果不这样做,而是直接做amp;运算那么高十六位所代表的部分特征就可能被丢失将高十六位无符号右移之后与低十六位做异或运算使得高十六位...博文来自:Bai_xing_yu的博客

  Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射...博文来自:zha_zi的专栏

  1.当我们发现无法联网时,我们运行下面命令或者ping命令 ip  addr 结果没有显示局域网的IP地址 2.我们去修改网卡配置文件,把网络连接打开 cd / cd  /etc/sys...博文来自:sfeng95的博客

  在我刚刚过去的研究生毕设中,我在ImageNet数据集上验证了图像特征二值化后仍然具有很强的表达能力,可以在检索中达到较好的效果。而Bengio大神的这篇文章,则不止于将特征二值化,而是要将权重和每层...博文来自:雨石

  原文地址:因为需要用,所以才翻译了这个文档。但总归赖于英语水平很有限,翻译出来的中文有可能...博文来自:ymj7150697的专栏

  Unity一键打包工具,一键生成几十个平台/渠道的安装包。博文来自:夜风的BLOG

  注1:RUtils是我偶然发现的一个工具包,它建立在Rserve之上,可以很大程度上简化我们的程序,关于Rserve网络上有很多相关的内容,这里不对其进行介绍,比如这里:博文来自:竹叶青的专栏

  好长时间之前做过的一个项目 , 其中设计到用Unity模拟卡拉OK歌词过渡的效果 , 如下图所示 ↓ , 这里简单把原理部分分享一下. 演示效果 ↓ 实现歌词动态调整功能 实现动态读取歌...博文来自:月儿圆

  docx4j官方提供了一些例子,本文只是其中一部分应用的简单例子。需要注意的地方是页眉和页脚,必须创建对应关系才能起作用。页眉和页脚添加图片的时候,第二个参数sourcePart是必须的,调用的cre...博文来自:偶尔记一下

  扫二维码关注,获取更多技术分享 本文承接之前发布的博客《 微信支付V3微信公众号支付PHP教程/thinkPHP5公众号支付》必须阅读上篇文章后才可以阅读这篇文章。由于最近一段时间工作比较忙,...博文来自:Marswill

  推荐 分享一个大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!推荐...博文来自:strongerHuang的专栏

  Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的Thread...博文来自:u011860731的专栏

  这篇文章要表达的并非数据库相关的知识,而是如何使用DBIOWrapper。       DBIOWrapper是一个工作在Windows下、对ODBC式数据访问进行了小型封装的库。其设计目标是提供极简...博文来自:哈哈 哈 哈哈,哈 哈 哈哈哈

  强连通分量: 简言之 就是找环(每条边只走一次,两两可达) 孤立的一个点也是一个连通分量   使用tarjan算法 在嵌套的多个环中优先得到最大环( 最小环就是每个孤立点)   定义: int Ti...博文来自:九野的博客

  安装oracle 9i后,居然把刚刚更改的数据库管理员密码给忘了,又不重新安装,太麻烦了,试了好久,终于修改成功了。1、运行到C盘根目录2、输入:SET ORACLE_SID = 你的SID名称3、输...博文来自:llxsharp的专栏

  Cocos2d-x 2.2.3 使用NDK配置编译环境2014年6月11日 Cocos2d-x 3.0以下的开发环境的配置恐怕折磨了很多人,使用cygwin配置编译环境足够让初学者蛋疼一阵子了。本篇博...博文来自:巫山老妖

  jquery/js实现一个网页同时调用多个倒计时(最新的) 最近需要网页添加多个倒计时. 查阅网络,基本上都是千遍一律的不好用. 自己按需写了个.希望对大家有用. 有用请赞一个哦! //js ...博文来自:Websites

  摘要:为了协助处理器完成初始化和控制系统操作,80x86提供了一个标志寄存器和几个系统寄存器。Eflags用于控制任务切换、中断处理、指令跟踪和权限访问。系统寄存器用于内存管理和控制处理器操作。 1...博文来自:河西无名式

  题目点评 数据类型是所有程序都会涉及到的,是计算机语言比较基础知识,这种问题被问到的可能性其实并不大,这样的题目只要花点时间把它记下来就好了,难易程度一般。  两大类: 栈:原始数据类型(Und...博文来自:雄领IT的专栏

  今天在本地做了修改,后来又不想要这次修改的内容,想要还原到修改之前的状态,有一个比较省力的方法,直接从git服务器对应的分支获取覆盖本地的程序。 命令如下:git checkout -f 这样就...博文来自:leedaning的专栏

  有时我们需要绘制热图,用x轴、y轴表示两维数据,用颜色表示第三维 第一步:需要准备三列数据,如图1,这里我用U表示x轴数据,它的取值范围为[0-1],间隔为0.05,E表示y轴,取值范围也是[0-1]...博文来自:SunCherryDream的专栏

  本文介绍如何使用VS2015作为编译开发环境,调用OpenCV3.31和Qt5.9.1写图像处理的GUI。 1.目录结构 假设我们要创建一个名为VideoZoom的工程,那么首先按下图构建目录结构...博文来自:zhhp1001的博客

  jyxmust:想请教一下,引用链是如何建立起来的,还有就是怎么判断一个对象(比如在某方法new 一个对象)是不是在roots 引用链里面?

http://linkzoo.net/tongliansuanfa/248.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有