开篇

本文基于 jdk1.8 讲述 HashMap 的 hash 算法,但是不会详细介绍其他相关内容(比如用法,底层数据结构)。所以必须事先知晓下面几点:

HashMap 的底层数据结构是数组,在数组的基础上再去考虑链表或者红黑树

put 一个 key-value 时,会先计算出在数组中的索引位置,再考虑剩下的步骤

位运算操作(异或,与)

java 运算符优先级

正文

HashMap 是基于 key-value 形式存放元素的,所使用的方法是 put(key, value)。

1. HashMap 的 put 方法源码

// 再次强调这是 jdk1.8 源码

public V put(K key, V value) {

// 这里调用 putVal() 方法

// 传入的第一个参数:是根据 key 计算出的 hash 值

return putVal(hash(key), key, value, false, true);

}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {

Node[] tab; Node p; int n, i;

// 获取数组的长度

if ((tab = table) == null || (n = tab.length) == 0)

n = (tab = resize()).length;

// 计算元素在数组中的索引位置

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newNode(hash, key, value, null);

else {

// 忽略部分代码

}

}

2. 从上面的源码中提取出两个代码片段

2.1 片段 1 - 计算 hash 值

static final int hash(Object key) {

int h;

return (key == null) ?

0 :

(h = key.hashCode()) ^ (h >>> 16);

}

如果 key 为 null,hash == 0

否则

先取出 key 的 hashCode 值,得到 h1

然后对 h1 右移 16 位,得到 h2

最后将 h1 和 h2 进行异或运算,得到最终的 hash 值

举个例子吧:

先获得 key 的 hashCode 值,得到 h1

1111 1111 1111 1111 1010 1010 1010 1010

对 h1 右移 16 位,得到 h2

0000 0000 0000 0000 1111 1111 1111 1111

最后将 h1 和 h2 进行异或运算

1111 111 1111 1111 0101 0101 0101 0101

图解 1

图解 2

结论如下:

1. 最终结果就是将 h1 的高 16 位 和低 16位进行了异或运算。

2. 达到的效果就是混合原始哈希码的高位和低位,以此来加大低位的随机性。

3. 顺带着,低 16 位可以同时拥有高 16 位的信息。

2.2 片段 2 - 计算元素在数组中的索引位置

i = (n - 1) & hash

如果让我们来做,通常会想到用下面取模的方式计算索引。

i = hash % n

其实,上面两种算法得到的结果是一样的(自行验证),就当这是一个数学公式吧。

【前提是 HashMap 的数组长度要取2的整次幂,这也说明了为什么 HashMap 的初始容量不能随便给】

但是两者相比而言,位运算的效率会更高,所以 HashMap 用了第一种算法。

总结

当 HashMap 的数组长度是 2 的整次幂时,(n - 1) & hash与 hash % n计算的结果是等价的,而后者是更容易想到的办法,前者是更有效率的办法。

HashMap 的 hash 算法(看起来分了好几步),其实就是把 hashCode 值的高 16 位 与 低 16 位进行了异或运算,目的就是增大随机性。

java hashmap hash算法,jdk1.8 中 HashMap 的 hash 算法和数组寻址相关推荐

  1. jdk1.8中HashMap扰动函数及数组长度为什么是2的n次方介绍

    文章目录 前言 一.什么是二进制? 二.计算机采用二进制的原因 三.十进制与二进制相互转换 十进制转成二进制 二进制转换为十进制 与.或.异或运算 按位异或 按位与运算 按位或运算 Jdk1.8中Ha ...

  2. [Java]JDK1.7中HashMap的并发死链

    [Java]JDK1.7中HashMap的并发死链 HashMap的并发死链现象发生在扩容时,在扩容过程中**transfer()**方法负责把旧的键值对转移到新的表中,其代码如下: void tra ...

  3. JDK1.7和JDK1.8中HashMap是线程不安全的,并发容器ConcurrentHashMap模型

    一.HashMap是线程不安全的 前言 只要是对于集合有一定了解的一定都知道HashMap是线程不安全的,我们应该使用ConcurrentHashMap.但是为什么HashMap是线程不安全的呢,之前 ...

  4. 七、JDK1.7中HashMap扩容机制

    导读 前面文章一.深入理解-Java集合初篇 中我们对Java的集合体系进行一个简单的分析介绍,上两篇文章二.Jdk1.7和1.8中HashMap数据结构及源码分析 .三.JDK1.7和1.8Hash ...

  5. JDK1.7中HashMap底层实现原理

    JDK1.7中HashMap底层实现原理 一.数据结构 HashMap中的数据结构是数组+单链表的组合,以键值对(key-value)的形式存储元素的,通过put()和get()方法储存和获取对象. ...

  6. Day1、为什么JDK1.8中HashMap从头插入改成尾插入

    目录 Day1.为什么JDK1.8中HashMap从头插入改成尾插入 存储方式 静态常量 插入元素 扩容 拓展问题 1.为什么JDK1.8采用红黑树存储Hash冲突的元素? 2.为什么在长度小于8时使 ...

  7. 八、JDK1.8中HashMap扩容机制

    导读 前面文章一.深入理解-Java集合初篇 中我们对Java的集合体系进行一个简单的分析介绍,上两篇文章二.Jdk1.7和1.8中HashMap数据结构及源码分析 .三.JDK1.7和1.8Hash ...

  8. 详述 JDK1.7 中 HashMap 会发生死链的原因

    文章目录 前置知识 死循环执行步骤1 死循环执行步骤2 死循环执行步骤3 解决方案 总结 前置知识 HashMap死循环是一个比较常见.比较经典的问题,在日常的面试中出现的频率比较高,所以接下来咱们通 ...

  9. 【死链】JDK1.7中HashMap在多线程环境的并发问题源码分析

    文章目录 一.HashMap在JDK1.7中的并发问题 二.死链如何产生? 三.如何解决HashMap并发问题 参考文献 一.HashMap在JDK1.7中的并发问题 在JDK1.7中的HashMap ...

最新文章

  1. 将某表一行数据的某些字段插入到该表
  2. Android 使用jtds远程访问数据库
  3. json文件读取之reader.onload中的定义的变量在其函数外部进行处理
  4. mysql数据库 day05
  5. Tcpdump抓包实操
  6. 为什么不敢和别人竞争_孩子在学校不敢竞争?你该怎么做
  7. Android----- MD5加密(登录注册得到与IOS相同的加密值,并且解决两个平台汉字加密不相同问题)...
  8. 数据接口复习 3 stack and queue
  9. 外卖类应用的竞争与趋势
  10. Latex 中文使用方法和示例——分别基于MiKTeX(CTeX套装)、TeXLive 编译系统测试CJK、ctex 宏包,PDFLaTeX、XeLaTeX编译命令及GBK、UTF-8文件编码的使用
  11. 微信小程序云开发之云数据库查询及动态输入
  12. 身份证号码验证(直接调用idCardValidate(String idCard) )
  13. Niagara模块微信公众号连接
  14. 2023 年的 Web Worker 项目实践
  15. 学习计算机嵌入式的笔记汇总
  16. 如何使用ttf字体文件
  17. (附源码)springboot福佳生活超市进销存管理系统 毕业设计261620
  18. 【面试题】网易互娱(游戏)2020校招在线笔试-游戏研发第一批[水平线]
  19. 提高独立站转化率的小技巧
  20. 机房计算机怎么查找192文档,计算机专业机房简介

热门文章

  1. 零基础入门天池NLP赛事之——新闻文本分类(5)
  2. 异质性分析:系数平滑可变模型
  3. 关于Latex中生僻字显示问题
  4. 摄像头8mm可以看多远_折叠屏、透明屏、卷曲屏、拼接屏、屏下摄像头...未来屏显的先机都在这里...
  5. 解决 iPhone X 屏幕底部空白问题
  6. 选择大于努力,错失字节跳动数亿身价,含泪分享
  7. [MICCAI2019]Multi-view Learning with Feature Level Fusion for Cervical Dysplasia Diagnosis
  8. mysql 怎么打开dmp_mySQL 中怎么将dmp文件导入数据库
  9. 互联网银行分化:头部优势凸显,尾部承压明显
  10. 《人工智能》之语音识别概述