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.从 ...
随机推荐
- 解决 EntityFrameworkCore tool 3.1 init.ps1 is not recognized 问题
昨天将项目升级到.net core 3.1后, 打开vs2019 Package Manager Console后突然发生了错误,如下 最终导致EntityFramework 迁移相关命令都不能正常使 ...
- linux下免密登录配置
1.首先大家先开三台虚拟机 2.回到首层. 2.1:编辑文件: vim /etc/ssh/sshd_config 3:在master的linux上生成ssh密钥: ssh-keygen -t r ...
- Tensorflow Cpu不支持AVX
Tensorflow从1.6开始从AVX编译二进制文件,所以如果你的CPU不支持AVX 你需要 从源码编译 下载旧版 从源码编译比较麻烦,如果你是初学的话,我建议使用旧版. 安装旧版: pip3 in ...
- eclipse中 sec/test/resource 文件夹消失怎么设置?
右键改包--->build path --->Configure bulid path 按 add Folder 搞定.....
- 编译Uboot时出错:【已解决】 /bin/bash: arm-linux-gcc: command not found dirname: missing operand Try 'dirname --help' for more information.
编译Uboot时出错: 错误信息如下: /bin/bash: arm-linux-gcc: command not found dirname: missing operand Try 'dirnam ...
- cinder api启动过程源码分析
1.启动cinder-api服务 当你通过cinder-api命令(如:/usr/bin/cinder-api --config-file /etc/cinder/cinder.conf)启动api服 ...
- call、apply、bind 的用法
例1 obj.objAge; //17 obj.myFun() //小张年龄undefined 例2 shows() //盲僧 比较一下这两者this 的差别,第一个打印里面的this 指向obj,第 ...
- Python输入input、输出print
1.输入input input是用于输入数据给变量.通过键盘输入的是字符串,如果需要其他格式,需要做转换.比如int.float类型数据,int() 如下是一个例子: 如果a不进行int转换,那么输入 ...
- ES6--let,解构赋值,promise && ES7--async
ES-->IE10.Google.火狐 ES6 let 声明的关键字 不能重复声明 块级作用域 <input type="button" value="1&q ...
- android开发之splash闪屏页判断是否第一次进入app代码
package com.david.david.zhankudemo.activity; import android.app.Activity; import android.content.Con ...