一、简介

大家都知道,HashMap中定位到桶的位置 是根据Key的hash值与数组的长度取模来计算的。

JDK8中的hash 算法:

    static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

取模算法:

hash(key)&(length-1)

二、深入分析

1、取模算法为什么用的是位与运算?

由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快。

对2的倍数取模,只要将数与2的倍数-1做按位与运算即可。

对原理感兴趣的可以参考【Java基础】14、位与(&)操作与快速取模

2、为什么不直接使用key.hashcode()进行取模运算?

我们知道hash的目的是为了尽量分布均匀。

取模做位与运算的时候,实际上刚刚开始数组的长度一般比较小,只利用了低16位,高16位是用不到的。这种情况下,产生hash冲突的概率会大大增加。

这样设计保证了对象的hashCode的高16位的变化能反应到低16位中,相比较而言减少了hash冲突的情况 。

选用亦或的方式是因为&和|都会使得结果偏向0或者1 ,并不是均匀的概念。

3、String的hashCode()深入分析

public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value; for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}

推导出的公式如下:

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

举个例子推导计算一下:

假设 n=3
i=0 -> h = 31 * 0 + val[0]
i=1 -> h = 31 * (31 * 0 + val[0]) + val[1]
i=2 -> h = 31 * (31 * (31 * 0 + val[0]) + val[1]) + val[2]
h = 31*31*31*0 + 31*31*val[0] + 31*val[1] + val[2]
h = 31^(n-1)*val[0] + 31^(n-2)*val[1] + val[2]

3.1、为什么使用31作为计算的因子呢?

  • 选择质数作为乘子,会大大降低hash冲突的概率。质数的值越大,hash冲突率越低
  • 31参与乘法运算,可以被 JVM 优化,31 * i = (i << 5) - i
  • 使用 101 计算 hash code 容易导致整型溢出,导致计算精度丢失
 

【Java深入研究】11、深入研究hashmap中的hash算法的更多相关文章

  1. HashMap中的hash算法总结

    前言 算法一直是我的弱项,然而面试中基本是必考的项目,刚好上次看到一个HashMap的面试题,今天也来学习下 HashMap中的hash算法是如何实现的. 数学知识回顾 << : 左移运算 ...

  2. HashMap中的hash算法中的几个疑问

    HashMap中哈希算法的关键代码 //重新计算哈希值 static final int hash(Object key) { int h; return (key == null) ? 0 : (h ...

  3. hashCode及HashMap中的hash()函数

    一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是根据关键码值(Key value)而直接进行访问的数据结构 ...

  4. [ 转载 ]hashCode及HashMap中的hash()函数

    hashCode及HashMap中的hash()函数   一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是 ...

  5. HashMap 中的 hash 函数

    1. 什么是 hash 函数 hash 函数,即散列函数,或叫哈希函数.它可以将不定长的输入,通过散列算法转换成一个定长的输出,这个输出就是散列值.需要注意的是,不同的输入通过散列函数,也可能会得到同 ...

  6. HashMap中的hash函数

    在写一个HashSet时候有个需求,是判断HashSet中是否已经存在对象,存在则取出,不存在则add添加.HashSet也是通过HashMap实现,只用了HashMap的key,value都存储一个 ...

  7. 图像相似度中的Hash算法

           度量两张图片的相似度有许多算法,本文讲介绍工程领域中最常用的图片相似度算法之一--Hash算法.Hash算法准确的说有三种,分别为平均哈希算法(aHash).感知哈希算法你(pHash) ...

  8. PHP中各种Hash算法性能比较

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  9. php中各种hash算法的执行速度比较

    更多内容推荐微信公众号,欢迎关注: PHP中的Hash函数很多,像MD4.MD5.SHA-1.SHA-256.SHA-384.SHA-512等我们比较常见,那么各个哈希的执行速度呢? $algos = ...

随机推荐

  1. Rxjava学习笔记

    1.使用Observable.range(int start, int count)创建一个发射特定整数序列的Observable,第一个参数为起始值,第二个为发送的个数,如果为0则不发送,负数则抛异 ...

  2. 201671010450-姚玉婷-实验十四 团队项目评审&课程学习总结

    项目 内容 所属科目 软件工程http://www.cnblogs.com/nwnu-daizh 作业要求 https://www.cnblogs.com/nwnu-daizh/p/11093584. ...

  3. CSV读取

    可以在Excel中编辑好后  另存为CVS文件

  4. 31 树莓派外接Oled屏幕

    http://shumeipai.nxez.com/2017/09/13/solve-the-raspberry-pi-drive-oled-problem.html

  5. TypeScript 解构和展开

    解构数组 解构数组元素 let input = [1, 2]; let [first, second] = input; console.log(first,second); 交换值 [first, ...

  6. js中的自动包装机制

    有一行语句: 1.toString() //error 那么问题来了,为什么报错? 我的第一想法就是1是一个基本类型,所以它没有toString方法 嗯,理直气壮 接下来有大佬show me code ...

  7. [THUPC2019]过河卒二(组合数学,容斥原理)

    以后都懒得写题目大意和数据范围了. hz学长的题其实也不那么毒瘤吗.比CDW的好多了 先考虑没有障碍怎么做. 首先发现,答案相当于一个左下角是 $(1,1)$,右上角是 $(n+1,m+1)$ 的棋盘 ...

  8. vue.config.js 配置 scss,less,sass全局配置 vuecli3

    module.exports = { /* 部署生产环境和开发环境下的URL:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath */ public ...

  9. Salesforce 开发整理(二)报表开发学习

    Salesforce提供了强大的报表功能,支持表格.摘要.矩阵以及结合共四种形式,本文探讨在站在开发的角度要如何理解报表. 一:查询报表基本信息报表在Sales force中是Report对象,基本的 ...

  10. Linux上安装git并在gitlab上建立对应的项目

    1.CentOS上面安装git我所用的CentOS为CentOS6.5,其他版本没有测试. yum install git 安装之后查看git版本信息 git --version 2.配置git信息g ...