HashMap原理总结
来总结一下HashMap的原理
1.HashMap当中有一个内部类,它叫Node,然后这个Node呢,它其实是实现了Map.Entry接口,这个接口当中有几个抽象的方法和几个具体的方法。其中Map.Entry<K,V>是一个泛型的元组。
2.Map.Entry接口中有如下抽象方法:
- getKey()
- getValue()
- setValue()
- hashCode()
- equals
3.Node的私有变量如下:
- hash
- key
- value
- Next node
其中HashMap的核心是hashcode的生成算法,hashCode的生成算法如下:
Objects.hashCode(key) ^ Objects.hashCode(value);
它是先通过得到Key和value的hashcode,然后对2个值进行异或操作后得到的值。
其中Object.hashCode是一个native的方法。
public native int hashCode();
其中Node的equals方法,传入的对象是object,只有当object的类型是map.entry并且,当前对象的key和value都和传入的key,value一致,那样才会返回相等。
下面的这个方法,是计算hash值的方法。它是通过key去计算,然后把拿到的hashcode和它右移16位的结果进行异或操作,具体回头再看为什么,我也不知道。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
hashMap里面还有一个entrySet的成员变量,它是一个set 的集合,这里面的transient关键字不太懂,回头再看看。
transient Set<Map.Entry<K,V>> entrySet;
HashMap里面有一个非常重要的方法,叫做putVal()方法。这算是里面最核心的一个方法了,弄懂了这个方法,80%的HashMap相关的知识都能弄懂了
首先是有2个Node的声明,一个是tab,一个是p.
Node<K,V>[] tab; Node<K,V> p; int n, i;
下面我们来解析一下PutVal方法,如果table为空,或者table的长度为0,重置table的长度。
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
首先是下面的代码会利用到上面的代码,n得出了一个结果,那就是resize()后的结果,下面的n-1就是“”最后“”一个元素
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
下面的代码就是上面的tabl[x]里面的逻辑,这里面用到了按位与的一个运算:为什么要这么做?不知道。
来做一个小小的补充,这里要先复习一下按位与的结果操作,什么时候获取什么值,如果hash是一个负数,那又是什么情况呢?
(n - 1) & hash
我猜想的是,如果“”找到的“”元素为null,那么新建一个node元素。并且这个node元素的next为空。否则执行else里面的逻辑。
----------------------------------------我是分割线---------------------------------------------
首先putVal方法会去计算这个key的hash值。
首先我觉得要明白hash算法的真谛,网上找的这句话,说得不错:要找到散列为同一个值的两个不同的输入,在计算上是不可能的,所以数据的哈希值可以检验数据的完整性。
当第一次进入putval方法的时候,table是空的,所以肯定要进行一个resize操作,不光是table,连threshold都是0,所有的东西都未能初始化的情况下,这个时候,应该进入如下逻辑:
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
这个时候,newCapicity的话就变成了初始值16,newThr变成了初始化的Threhold,如果是这种情况下的话,就会新建一个长度为16的Node<K,V>[]数组,最后返回newTable,注意,resize操作的返回对象。
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
在下面的例子中,hash值是一个非常大的值,换算成2进制,它是32位长度的一个2进制,用按位与的操作是最快的,因为计算机内部结构就是二进制的。
if ((p = tab[i = (n - 1) & hash]) == null)
注意!!!它先填充的是tab[10]的内容,也就是说,并没有从0开始填充,这是违背我们直觉的一件事情。

然后让modCount++,
最后,如果负载因子小于size,那么,hashmap会自动扩容。
if (++size > threshold)
resize();
随后执行afterNodeInsertion方法,这个方法在Hashmap当中是一个空的方法,API里面介绍的是为LinkedHashMap所用,所以这里不再做讨论。还有注意下,如果是新建的hashMap第一次putval,那么它的返回值为null.
要注意一点,新建一个HashMap,它并不是独立存在的,在你把你的key添加进去之前,它还会添加非常多的其他的KEY,也就是我们所说的:系统路径,所以最后得出的结果就是,如果你是一个新的HashMap,那么,你添加了一个KEY,肯定这里面不止一个KEY。


大家可以观察到,当SIZE=13的时候,

其实是自动进入了resize这个方法的,你看我断点都进来了。这就证明了hashmap的自动扩容机制。

那么为什么会有这么多的Node被添加进来呢?原因只有一个,就是我们用idea启动项目的时候,一些类其实是用到了HashMap的,它优于我们调试的时候进入的HashMap,所以刚才大家才会看到那么多的节点被添加到hashMap当中去。
当我把在putVal上的断点去掉以后,就进入了如下代码块,验证了我的猜想。

另外还有一个很有趣现象,我用单元测试,新建了一个HashMap,结果。。。你发现没有,jdk里面已经填充了4项了,原来,我们认为的Hashmap,有多少项,就add多少项的观点其实是错误的!!!

下面我们再来看看如下代码,传入的hash和之前的hash进行对比,这里面可能大家有一些迷糊,当然包括我也看不懂,不过从这里可以获取一个非常重要的信息,这么做的方式就是为了避免一个hashmap钟可能出现“相同”的hash对象,我是这么理解的,如果有高人,可以来解释下为什么这样。
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
下面的代码也很明白了,如果不是上面都 ,那么如果是树节点,那么就执行下面的逻辑,此处不再深究。
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
下面的代码的含义是,如果p.next为空的话,那么新建一个节点,并追加到尾部,这种情况,就是当p指向最后一个节点的时候才会出现的情况。
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
后面的代码有点感觉太难啃了,先暂时就这样吧,今天的HashMap分析得还不太完整,并且不太合理,希望大家能多提宝贵建议。
HashMap原理总结的更多相关文章
- ==和equasl、hashmap原理(***)
public class String01 { public static void main(String[] args) { String a="test"; String b ...
- Java基础-hashMap原理剖析
Java基础-hashMap原理剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是哈希(Hash) 答:Hash就是散列,即把对象打散.举个例子,有100000条数 ...
- Java:HashMap原理与设计缘由
前言 Java中使用最多的数据结构基本就是ArrayList和HashMap,HashMap的原理也常常出现在各种面试题中,本文就HashMap的设计与设计缘由作出一一讲解,并解答面试常见的一些问题. ...
- HashMap原理(二) 扩容机制及存取原理
我们在上一个章节<HashMap原理(一) 概念和底层架构>中讲解了HashMap的存储数据结构以及常用的概念及变量,包括capacity容量,threshold变量和loadFactor ...
- java中HashMap原理?
参考:https://www.cnblogs.com/yuanblog/p/4441017.html(推荐) https://blog.csdn.net/a745233700/article/deta ...
- 2021超详细的HashMap原理分析,面试官就喜欢问这个!
一.散列表结构 散列表结构就是数组+链表的结构 二.什么是哈希? Hash也称散列.哈希,对应的英文单词Hash,基本原理就是把任意长度的输入,通过Hash算法变成固定长度的输出 这个映射的规则就是对 ...
- HashMap原理及源码分析
HashMap 原理及源码分析 1. 存储结构 HashMap 内部是由 Node 类型的数组实现的.Node 包含着键值对,内部有四个字段,从 next 字段我们可以看出,Node 是一个链表.即数 ...
- HashMap原理与优化
参考文献: HashMap的工作原理 java中HashMap重要性质和优化总结 一.HashMap的基本了解 基本定义:根据源代码的描述可知,HashMap是基于哈希表的Map接口的实现,其包含了M ...
- HashMap原理详解
HashMap 概述 HashMap 是基于哈希表的 Map 接口的非同步实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.此类不保证映射的顺序,特别是它不保证该顺序恒久不 ...
- 面试题 HashMap 原理
HashMap与HashTable的区别 总结: HashMap是用来代替HashTable的类,一般建议使用HashMap.最核心的区别:HashTable的方法是同步的(线程安全),而HashMa ...
随机推荐
- POJ 1163 The Triangle【dp+杨辉三角加强版(递归)】
The Triangle Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 49955 Accepted: 30177 De ...
- 在R12下加载Java Bean,配置FORMS_WEB_CONFIG_FILE文件/通过AutoConfig实现Form Server配置文件的修改
1.定位模版文件$AD_TOP/bin/adtmplreport.sh contextfile=$CONTEXT_FILE target=$FORMS_WEB_CONFIG_FILE以上命令,通过查看 ...
- msf
show exploit show payload msf使用数据库加快搜索,不然每次都等半天 service postgresql startmsfdb reinitmsf > db_rebu ...
- 听说 Android 9.0 要禁用 @Hide Api 的调用,你怎么看?
Android 9.0? Hi,大家好,我是承香墨影! 距离 Android 8.0 发布,已经过了五个月,虽然现在占有率并不高,不过呢,Google 已经着手准备下一版本的 Android 系统. ...
- TI-RTOS 之 GPIO中断(按键)
TI-RTOS 之 GPIO中断(按键) 前面已经用过LED, 定时器,这次来了解GPIO的中断是怎么用的,从CC1310+TI-RTOS的例程可以直接找到相应的例子程序,它的关键是在于要使能中断,也 ...
- oracle 数据库——知识点总结(加示例)
新入oracle数据库,把目前学到的知识点记录下来,可能都比较基础,但还是比较全的,里面的示例都是自己在PL/SQL中跑过的,如果有错误,还望各位大侠指出哈. 创建用户 1.创建用户(使用管理员身份创 ...
- HDU 5538 House Building(模拟——思维)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5538 Problem Description Have you ever played the vi ...
- error: Failed dependencies:解决
error: Failed dependencies:解决 使用rpma安装安装包时,会出现 error: Failed dependencies: 意思是 失败的依赖 解决方法: 在安装包后面加两个 ...
- html dl dt dd标签元素语法结构与使用
dl dt dd认识及dl dt dd使用方法 标签用于定义列表类型标签. dl dt dd目录 dl dt dd介绍 结构语法 dl dt dd案例 dl dt dd总结 一.dl dt dd认识 ...
- JS_全
<script src="jquery-1.9.1.js" type="text/javascript"></script> <s ...