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.从 ...
随机推荐
- angular中a标签带请求头下载excel
<!DOCTYPE html> <html lang="en" ng-app="app"> <head> <meta ...
- Elasticsearch+SpringBoot报NoNodeAvailableException解决方案
Elasticsearch整合SpringBoot 首先大家在整合的时候一定要注意版本兼容问题,此问题尤为重要 Elasticsearch简称Es 在使用SpringBoot整合Elasticsear ...
- day1 linux常用命令(一)
- Python钉钉报警及Zabbix集成钉钉报警
钉钉报警设置 创建群机器人 11111 接口地址 发送短消息 发送普通消息 import requests import json url = 'https://oapi.dingtalk.com/r ...
- PC,移动端H5实现实现小球加入购物车效果
HTML部分: <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" ...
- 「完整案例」基于Socket开发TCP传输客户端
1 程序界面设计 TCP客户端在上位机开发中应用很广,大多数情况下,上位机软件都是作为一个TCP客户端来与PLC或其他服务器进行通信的.TCP客户端的主要功能就是连接服务器.发送数据.接收数据.断开 ...
- 计算机网络-网络层(6)ICMP协议
互联网控制报文协议(ICMP,Internet Control Message Protocol),被主机和路由器用来彼此沟通网络层的信息 ICMP报文是承载在IP分组中的,即lCMP报文是作为IP有 ...
- 结对项目:四则运算题目生成器(C)
一.Github项目地址:https://github.com/Spartaright/myapp(合作人:梁天龙.赖佑铭) 二.PSP表格(如下图) 1.项目地址 PSP表格 PSP2.1 Pers ...
- 微众银行FATE联邦学习框架
参考:https://github.com/webankfintech/fate https://www.fedai.org/#/ 一.Docker Standalone 安装 FATE $ sh b ...
- Tmux安装和使用
1.What's tmux tmux 是一个终端复用器: 可以激活多个终端或窗口, 在每个终端都可以单独访问,每一个终端都可以访问,运行和控制各自的程序.tmux类似于screen,可以关闭窗口将程序 ...