HashMap 源码解毒
PUT 方法解毒:


hashcode 高低16进行异或运算,尽量降低哈希冲突的概率
如果数组很小,hashcode的高位就不能被很好利用。
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
// 如果tab为空或者长度为0,则需要初始化(默认大小16,默认扩容门槛0.75*16)
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// 通过((n - 1) & hash)找到数组中合适的位子
if ((p = tab[i = (n - 1) & hash]) == null)
// 如果数组中为空(数组中会存放Node链表或者红黑树) 新建Node节点
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
// 如果第一个节点的值等于插入的value
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);
else {
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;
}
}
// 如果原来存在Node,是不是需要替换?onlyIfAbsent
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
// 大于阈值进行扩容 比如阈值是12 size==12,而不是modCount==12,时候扩容
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
// 如果旧容量大于等于最大容量,就不能再扩容了
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
// 容量是2倍旧容量
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
// 新阈值是旧阈值2倍
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
// 计算新阈值
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
// 创建新数组
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
HashMap 源码解毒的更多相关文章
- HashMap 源码解析
HashMap简介: HashMap在日常的开发中应用的非常之广泛,它是基于Hash表,实现了Map接口,以键值对(key-value)形式进行数据存储,HashMap在数据结构上使用的是数组+链表. ...
- HashMap源码分析
最近一直特别忙,好不容易闲下来了.准备把HashMap的知识总结一下,很久以前看过HashMap源码.一直想把集合类的知识都总结一下,加深自己的基础.我觉的java的集合类特别重要,能够深刻理解和应用 ...
- JAVA源码分析-HashMap源码分析(一)
一直以来,HashMap就是Java面试过程中的常客,不管是刚毕业的,还是工作了好多年的同学,在Java面试过程中,经常会被问到HashMap相关的一些问题,而且每次面试都被问到一些自己平时没有注意的 ...
- Java集合---HashMap源码剖析
一.HashMap概述二.HashMap的数据结构三.HashMap源码分析 1.关键属性 2.构造方法 3.存储数据 4.调整大小 5.数据读取 ...
- 【转】Java HashMap 源码解析(好文章)
.fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...
- 【JAVA集合】HashMap源码分析(转载)
原文出处:http://www.cnblogs.com/chenpi/p/5280304.html 以下内容基于jdk1.7.0_79源码: 什么是HashMap 基于哈希表的一个Map接口实现,存储 ...
- HashMap源码解读(转)
http://www.360doc.com/content/10/1214/22/573136_78188909.shtml 最近朋友推荐的一个很好的工作,又是面了2轮没通过,已经是好几次朋友内推没过 ...
- HashMap源码剖析
HashMap源码剖析 无论是在平时的练习还是项目当中,HashMap用的是非常的广,真可谓无处不在.平时用的时候只知道HashMap是用来存储键值对的,却不知道它的底层是如何实现的. 一.HashM ...
- Java中HashMap源码分析
一.HashMap概述 HashMap基于哈希表的Map接口的实现.此实现提供所有可选的映射操作,并允许使用null值和null键.(除了不同步和允许使用null之外,HashMap类与Hashtab ...
- 转:【Java集合源码剖析】HashMap源码剖析
转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 您好,我正在参加CSDN博文大赛,如果您喜欢我的文章,希望您能帮我投一票 ...
随机推荐
- Transformer应用于时序任务:综述《Transformers in Time Series: A Survey》
2022年9月13日 21:28 摸鱼了一天,看看综述. 论文:Transformers in Time Series: A Survey GitHub: 阿里达摩院 2022的论文. 摘要 从两个角 ...
- 【赵渝强老师】在MongoDB中使用游标
一.什么是游标? 游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力. 游标实际上是一种能从包括多条数据记录的结果集 ...
- 掌握Docker:简化KES单机安装与管理的最佳实践
今天我们将继续深入探讨KES的单机安装,依然围绕Docker的使用展开.这一部分的内容将涵盖一些常见的陷阱以及在遇到问题时如何进行有效的反馈和解决.首先,我们需要找到官方的安装教程,确保以官方指南为主 ...
- 利用cv2.morphologyEx提取图像边界
cv2.morphologyEx(image, cv2.MORPH_GRADIENT, SE)可以参考这篇博客cv2.MORPH_GRADIENT:形态学梯度(morph-grad),可以突出团块(b ...
- 数据库排行榜|当 DB-Engines 遇见墨天轮国产数据库排行
提到数据库排名,此时脑海里浮现出的是什么?是 DB-Engines,还是墨天轮数据库排行?两者间有什么区别?下面来聊一下业内这两个知名数据库排名平台. 本篇文章约有 3000 字,预计阅读时间 7 分 ...
- 2022年第十八届 GOPS 全球运维大会资料分享
全球运维大会是国内第一个运维行业大会,面向互联网.金融.通信及传统行业广大运维技术人员,旨在传播先进技术思想和理念,分享业内最佳实践. 2022年第十八届 GOPS 全球运维大会(深圳站)共分为18个 ...
- ADO.NET 连接数据库 【vs2022 + sqlServer】
using System.Data; using System.Data.SqlClient; namespace Zhu.ADO.NET { internal class Program { pri ...
- 17 Transformer 的解码器(Decoders)——我要生成一个又一个单词
博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...
- 在Java程序中监听mysql的binlog
目录 1.背景 2.mysql-binlog-connector-java简介 3.准备工作 1.验证数据库是否开启binlog 2.开启数据库的binlog 3.创建具有REPLICATION SL ...
- 分享几个实用且高效的EF Core扩展类库,提高开发效率!
前言 今天大姚给大家分享3款开源且实用的EF Core扩展类库,希望能帮助你在使用 EF Core 进行数据库开发变得更加高效和灵活,提高开发效率. EF Core介绍 Entity Framewor ...
