Java源码之HashMap的hash篇
提到哈希,我们脑袋中立马就会闪过一个方法,就是hashCode(),没错。就是这个!
我们知道HashMap是通过 数组+链表 的结构进行数据存储的,有数组就会有索引,而HashMap内的数据要存储在哪块索引上,则是基于HashMap内部的hash方法计算出来的。
我们常用的 get put 也离不开这个 hash 方法。
我们先从hash方法入手!
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
首先通过 hashCode() 方法得到 h ,然后在把 h 无符号右移16位,最后通过异或算法得到hash值,我们找个key展开运算一下
假设有一个key
String key = "hello world";
那么这个key的hashCode的二进制为
0110 1010 1110 1111 1110 0010 1100 0100
然后把这个二进制数据向右无符号移动16位,得到如下
0000 0000 0000 0000 0110 1010 1110 1111
最后通过把高16位和低16位做异或运算均匀分布
0110 1010 1110 1111 1000 1000 0010 1011
给hash做异或运算主要还是为了降低hash冲突的概率(这个是查阅资料得知的)
我们说完hash的运算过程后,看一下HashMap里边都是哪里有用到吧
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
这三个方法,算是HashMap内最常用的三个方法了,可以看到从应用层传递进来的key全部都经过了hash(key)而比较细心的朋友们还会发现HashMap内数组的索引,是通过 i = (n - 1) & hash 计算得出的
我们接下来在展开一下索引计算公式
n是HashMap内的哈希表的长度,默认是16,每次扩容都是一倍一倍的扩容,就是 16 << 1 ,我们拿16来展开运算,而hash用上面的key来继续运算
i = (16 - 1) & hash
15的二进制结果是
0000 0000 0000 0000 0000 0000 0000 1111
hash的再拿过来用吧~(十进制:1794082859)
0110 1010 1110 1111 1000 1000 0010 1011
在通过&运算,可以得到(十进制:11)
0000 0000 0000 0000 0000 0000 0000 1011
十进制计算:
1794082859 & 15 = 11
1794082859 % 16 = 11
首先n在HashMap里的设定是永远都是2次幂,因为 2次幂 & hash(key) 等价于 hash(key) % n
而众所周知,& 比 % 效率要高10倍的。
但这个公式只有 n 是2次幂的时候才成立,所以才有了2次幂的设定。
HashMap的索引都是通过这个算法得出来的,所以HashMap查找起来特别快~
好了,通过这篇文章,大家应该也对HashMap的hash有点概念了。
Java源码之HashMap的hash篇的更多相关文章
- 浅析Java源码之HashMap
写这篇文章还是下了一定决心的,因为这个源码看的头疼得很. 老规矩,源码来源于JRE1.8,java.util.HashMap,不讨论I/O及序列化相关内容. 该数据结构简介:使用了散列码来进行快速搜索 ...
- JAVA源码分析-HashMap源码分析(一)
一直以来,HashMap就是Java面试过程中的常客,不管是刚毕业的,还是工作了好多年的同学,在Java面试过程中,经常会被问到HashMap相关的一些问题,而且每次面试都被问到一些自己平时没有注意的 ...
- Java源码学习:HashMap实现原理
AbstractMap HashMap继承制AbstractMap,很多通用的方法,比如size().isEmpty(),都已经在这里实现了.来看一个比较简单的方法,get方法: public V g ...
- Java源码之HashMap
一.HashMap和Hashtable的区别 (1)HashMapl的键值(key)和值(value)可以为null,而Hashtable不可以 (2)Hashtable是线程安全类,而HashMap ...
- 浅析Java源码之HashMap外传-红黑树Treenode(已鸽)
(这篇文章暂时鸽了,有点理解不能,点进来的小伙伴可以撤了) 刚开始准备在HashMap中直接把红黑树也过了的,结果发现这个类不是一般的麻烦,所以单独开一篇. 由于红黑树之前完全没接触过,所以这篇博客相 ...
- Java源码阅读HashMap
1类签名与注释 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cl ...
- Java源码解析|HashMap的前世今生
HashMap的前世今生 Java8在Java7的基础上,做了一些改进和优化. 底层数据结构和实现方法上,HashMap几乎重写了一套 所有的集合都新增了函数式的方法,比如说forEach,也新增了很 ...
- JAVA源码分析-HashMap源码分析(二)
本文继续分析HashMap的源码.本文的重点是resize()方法和HashMap中其他的一些方法,希望各位提出宝贵的意见. 话不多说,咱们上源码. final Node<K,V>[] r ...
- java源码之HashMap和HashTable的异同
代码版本 JDK每一版本都在改进.本文讨论的HashMap和HashTable基于JDK 1.7.0_67 1. 时间 HashTable产生于JDK 1.1,而HashMap产生于JDK 1.2.从 ...
随机推荐
- 下载的附件名总乱码?你该去读一下 RFC 文档了!
纸上得来终觉浅,绝知此事要躬行 Web 开发过程中,相信大家都遇到过附件下载的场景,其中,各浏览器下载后的文件名中文乱码问题或许一度让你苦恼不已. 网上搜索一下,大部分都是通过Request Head ...
- MySQL InnoDB表空间加密
从 MySQL5.7.11开始,MySQL对InnoDB支持存储在单独表空间中的表的数据加密 .此功能为物理表空间数据文件提供静态加密.该加密是在引擎内部数据页级别的加密手段,在数据页写入文件系统时加 ...
- mac启动 Apache JMeter 5.3 语言选择中文界面出现乱码 问题解决
问题重现 问题修复 出现这个问题,是因为,语言与外观不兼容导致,语言选“中文”,外观选“Metal” 细心的你,可能发现,为啥要重启2次呢???第一次设置完语言后,在设置外观,发现菜单不能选择,第二次 ...
- MySQL SQL概述
MySQL SQL概述 数据库的好处: •实现数据持久化 •使用完整的管理系统统一管理易 数据库的概念: DB:数据库(database):存储数据的“仓库”.它保存了一系列有组织的数据. DBMS: ...
- 贫血模型和DDD模型
贫血模型和DDD模型 1.贫血模型 1.1 概念 常见的mvc三层架构 简单.没有行为 2.领域驱动设计 2.1 概念(2004年提出的) Domain Driven Design 简称 DDD DD ...
- 快速排序算法简述及python的实现
def kp(arr, i, j): if i<j: #i=j时意味着一边只剩单个数据 base = kpgc(arr, i, j) kp(arr, i, base-1) #kp(arr, i, ...
- 团队作业1——团队展示&选题 (追忆少年)
目录 一,团队展示 1.1队名 1.2队员学号 1.3项目描述 1.4队员风采 1.5团队分工 1.6团队合照 1.7团队特色 (一)目标导向 (二)协作基础 (三)共同的规范和方法 (四)技术或技能 ...
- pytest与Allure集成
1.窗口的方式 重启jenkins,重新连接,继续上次的内容.(注意:点击launch,重新下载slave-agent文件,然后双击slave-agent文件进行连接.上次下载的slave-agent ...
- Java数据结构——图的DFS和BFS
1.图的DFS: 即Breadth First Search,深度优先搜索是从起始顶点开始,递归访问其所有邻近节点,比如A节点是其第一个邻近节点,而B节点又是A的一个邻近节点,则DFS访问A节点后再访 ...
- java23种设计模式—— 二、单例模式
源码在我的github和gitee中获取 介绍 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. ...