Java HashMap源码学习
Java HashMap源码学习
基本使用
包含创建,添加,删除,迭代,打印
val map = java.util.HashMap<Int, Int>()
map.put(1, 2)
map.put(2, 2)
map.put(3, 2)
map.remove(1)
map.forEach {println("it.key=${it.key}, it.value=${it.value}")
}
println(map)
分析源码
一贯原则,没用的帮兄弟们省掉了
简单介绍
package java.util;// AbstractMap,可以随机访问
public class HashMap<K, V> extends AbstractMap<K, V> {// 初始容量static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 最大容量static final int MAXIMUM_CAPACITY = 1 << 30;// 负载因子,当前容量超过最大容量*负载因子,开始扩容static final float DEFAULT_LOAD_FACTOR = 0.75f;// 链表大于8树化static final int TREEIFY_THRESHOLD = 8;// 树小于6链化static final int UNTREEIFY_THRESHOLD = 6;// 树化的最小容量static final int MIN_TREEIFY_CAPACITY = 64;// 存储key,valuestatic class Node<K, V> implements Map.Entry<K, V> {// 通过key中字段计算final int hash;final K key;V value;Node<K, V> next;Node(int hash, K key, V value, Node<K, V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}// 省略get,set等模板方法}
}
创建
// 负载因子
public HashMap() {this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
添加
public V put(K key, V value) {// 通过hash()对key进行一次hash()return putVal(hash(key), key, value);
}// 重点分析
final V putVal(int hash, K key, V value) {// tab,桶,就是数组// p,期望对象// n,当前桶容量// i,桶下标Node<K,V>[] tab; Node<K,V> p; int n, i;// 如果是第一次,通过resize()更新初始容量if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;// 与桶大小&计算,二次hash()// 刚好桶上没元素,直接在桶上更新if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {// e,辅助期望元素// k,桶下标元素的keyNode<K,V> e; K k;// 如果和桶第一个一样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)treeifyBin(tab, hash);break;}// 找到key一样的if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}e.value = value;}// 扩容if (++size > threshold)resize();return null;
}// key经过hashCode()与低位^,让高位也参与计算
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}// 二倍扩容
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;}// 二倍扩容else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&oldCap >= DEFAULT_INITIAL_CAPACITY)newThr = oldThr << 1; // double threshold}else if (oldThr > 0) // initial capacity was placed in thresholdnewCap = oldThr;// 第一次扩容else { // zero initial threshold signifies using defaultsnewCap = 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)// 通过hash&新桶容量,计算位置newTab[e.hash & (newCap - 1)] = e;// 树转移else if (e instanceof TreeNode)((TreeNode<K,V>)e).split(this, newTab, j, oldCap);// 链表else { // preserve order// lo,low,hi,high,high=桶容量/2+lowNode<K,V> loHead = null, loTail = null;Node<K,V> hiHead = null, hiTail = null;Node<K,V> next;do {next = e.next;// 如果在下标0位置if ((e.hash & oldCap) == 0) {if (loTail == null)loHead = e;elseloTail.next = e;loTail = e;}else {if (hiTail == null)hiHead = e;elsehiTail.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可以存储键值对
- 初始容量是16,每次扩容2倍数
- 先添加,后扩容
- 从尾部添加
后续
里面代码确实挺多,其中还包括树,以后分析并尝试重写
相关文章:
Java HashMap源码学习
Java HashMap源码学习 基本使用 包含创建,添加,删除,迭代,打印 val map java.util.HashMap<Int, Int>() map.put(1, 2) map.put(2, 2) map.put(3, 2) map.remove(1) map.forEach {println("it.key${it.key}, it.va…...
Gin中用于追踪用户的状态的方法?!!!
Gin中的Cookie和Session的用法 文章目录 Gin中的Cookie和Session的用法介绍Cookie代码演示 Session代码展示 介绍 cookie 和 session 是 Web 开发中常用的两种技术,主要用于跟踪用户的状态信息。 Cookie func (c *Context) Cookie(name string, value string, max…...
HTTP代理与HTTPS代理在工作流程上有哪些区别
HTTP代理和HTTPS代理都是常见的代理技术,可以实现隐藏客户端IP地址、突破网络封锁、加速网站访问、过滤网络内容等功能。本文将介绍HTTP代理和HTTPS代理在工作流程上的区别。 HTTP代理的工作流程 客户端向代理服务器发送HTTP请求 当客户端需要访问某个网站时&#x…...
Docker从认识到实践再到底层原理(二-2)|Namespace+cgroups
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…...
算法的概述
算法分析: 解决同一问题的算法可以有多种。 我们希望从中选出最优的算法,效率高或者存储空间小。为此,需要对算法进行评估,分析。 通常考虑两个度量: 1、 时间复杂度:算法运行时需要的总步数,…...
菜鸟教程《Python 3 教程》笔记(19):错误与异常
菜鸟教程《Python 3 教程》笔记(19) 19 错误和异常19.1 assert(断言)19.2 异常处理19.2.1 try/except19.2.2 try/except...else19.2.3 try-finally 语句 19.3 抛出异常19.4 用户自定义异常19.5 清理行为19.5.1 定义清理行为19.5.2…...
空气净化器上亚马逊美国站需要办理什么认证?空气净化器UL867测试报告如何办理?
空气净化器又称“空气清洁器”、空气清新机、净化器,是指能够吸附、分解或转化各种空气污染物(一般包括PM2.5、粉尘、花粉、异味、甲醛之类的装修污染、细菌、过敏原等),有效提高空气清洁度的产品,主要分为家用 、商用…...
SpringBoot的测试方案
写完代码后,测试是必不可少的步骤,现在来介绍一下基于SpringBoot的测试方法。 基于SpringBoot框架写完相应功能的Controller之后,然后就可以测试功能是否正常,本博客列举MockMvc和RestTemplate两种方式来测试。 准备代码 实体类…...
华为OD机考算法题:字符串解密
目录 题目部分 解读与分析 代码实现 题目部分 题目字符串解密题目说明给定两个字符串string1和string2。 string1是一个被加扰的字符串。string1由小写英文字母(a~z)和数字字符(0~9)组成,而加扰字符串由0~9、a~f 组…...
unity 锚点设置
锚点聚合情况: 一个2d物体的位置 pos x pos y 是中心点相对于锚点的偏移量: 中心点就是位置。 按住shift 锚点和中心点都会被设置: 按住Alt: 同时按住shift和alt : 中心点 锚点 UI元素在对应的位置上。 锚点拉伸情况…...
Hadoop:HDFS--分布式文件存储系统
目录 HDFS的基础架构 VMware虚拟机部署HDFS集群 HDFS集群启停命令 HDFS Shell操作 hadoop 命令体系: 创建文件夹 -mkdir 查看目录内容 -ls 上传文件到hdfs -put 查看HDFS文件内容 -cat 下载HDFS文件 -get 复制HDFS文件 -cp 追加数据到HDFS文件中 -appendTo…...
自定义封装异步任务组件,实现FutureTask功能
FutureTask 在 JDK1.8 后的异步编排API中的CompletableFuture,提供了 异步任务的成功回调、异常回调。 public class FutureTaskTest {public static void main(String[] args) throws Exception {CompletableFuture<String> future CompletableFuture.sup…...
【区块链 | IPFS】IPFS节点搭建、文件上传、节点存储空间设置、节点上传文件chunk设置
一、创建ipfs节点 通过ipfs init在本地计算机建立一个IPFS节点 本文有些命令已经执行过了,就没有重新初始化。部分图片拷贝自先前文档,具体信息应以实物为准 ipfs init initializing IPFS node at /Users/CHY/.ipfs generating 2048-bit RSA keypair.…...
【autodesk】浏览器中渲染rvt模型
使用Forge完成渲染 Forge是什么 为什么能够渲染出来rvt模型 Forge是由Autodesk开发的一套云端开发平台和工具集。在Forge平台中,有一个名为"Model Derivative"的服务,它可以将包括RVT(Revit)在内的多种BIM(…...
Python超入门(1)__迅速上手操作掌握Python
# 1.第一个代码:输出语句 # 1.第一个代码:输出语句 print("My dogs name is Huppy!") print(o----) print( ||| ) print("*" * 10) """ 输出结果: My dogs name is Huppy! o----||| ********** "&…...
后端面试话术集锦第 十四 篇:go语言面试话术
这是后端面试集锦第十四篇博文——go语言面试话术❗❗❗ 1. go数组、切片、扩容 go的数组和切片都是用来存储相同类型的数据集合。 数组是存储固定大小的集合,且为值引用。 但切片是存储无固定大小的集合,且为引用类型。 切片有三个属性,分别为指向指针的数组array,数组…...
Oralce集群管理-19C RAC 私有网络调整为BOND1
1 尝试在线添加私有网络的新接口 是否成功。 使用oifcfg命令在线添加新的网卡接口,在还没有配置bond1的条件下 也是可以添加成功的。 [gridorcldb1 ~]$ oifcfg getif eno3 192.168.224.0 global public ens3f0 10.2.0.0 global cluster_interconnect,asm eno…...
洛谷 Array 数论
题目: 对于长度为n的数组A,A中只包含从1到n的整数(可重复)。如果A单调不上升或单调不下降,A就可称为美丽的。 找出在长度为n时,有几个美丽的A。 思路: 这是一道数论题。 我们先找找“单调不递…...
简明SQL条件查询指南:掌握WHERE实现数据筛选
条件查询是用于从数据库中根据特定条件筛选数据行的一种方式,它避免了检索整个表中的数据。通常,使用 WHERE 子句来定义过滤条件,只有符合这些条件的数据行才会被返回。 SQL中的运算符有:、!、<、> 等,用于进行…...
通过HbaseClient来写Phoenix表实现
由于数据存储在Hbase上,并且上层使用了Phoenix来读写数据。并且由于数据的列字段不固定,并且可能由于Hbase表列和Phoenix的表列字段不一致,使用Phoenix写入的数据会导致写出报错的问题出现。所以这里直接使用HbaseClient写入到Hbase表中&…...
OpenClaw网页前端开发与优化全流程指南
OpenClaw网页前端开发与优化全流程指南 🌐 核心价值:OpenClaw实现"需求→设计→代码→优化→部署"全流程自动化,开发效率提升600%,页面加载速度提升300%,SEO评分提升85%,完全兼容React/Vue/Angul…...
从DCM到NII:医学影像数据处理中,为什么我劝你放弃保存回DCM格式?
从DCM到NII:医学影像数据处理中格式选择的深度实践指南 医学影像数据处理的流程中,文件格式的选择往往被忽视,却直接影响着后续分析的效率与兼容性。许多研究者习惯性地将处理后的数据保存回DCM格式,殊不知这可能在后续流程中埋下…...
EPSON机器人通信避坑指南:TCP/IP协议在LS3-401S上的常见问题与解决方案
EPSON机器人通信避坑指南:TCP/IP协议在LS3-401S上的常见问题与解决方案 在工业自动化领域,EPSON LS3-401S机器人凭借其高精度和可靠性广受青睐。然而,在实际部署过程中,TCP/IP通信问题往往成为工程师们的"拦路虎"。本文…...
基于多维特征与随机森林的就业状态预测模型构建与优化实践
1. 就业预测模型的应用场景与价值 就业状态预测听起来高大上,但说白了就是帮我们判断一个人接下来会不会失业,或者帮失业的人找到合适工作。我在金融行业做数据分析时,就遇到过银行需要评估贷款申请人还款能力的情况——其实核心就是预测对方…...
2025届必备的十大降重复率工具实测分析
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 用于学术论文、科研报告以及各类文档,提供查重与改写服务的在线工具是降重网站。…...
Wan2.2-I2V-A14B效果展示:动态运镜+光影变化的高质量视频样例
Wan2.2-I2V-A14B效果展示:动态运镜光影变化的高质量视频样例 1. 惊艳的视频生成能力 Wan2.2-I2V-A14B文生视频模型带来了令人惊叹的视频生成效果。这个私有部署镜像经过深度优化,能够根据文字描述生成具有专业级动态运镜和光影变化的高质量视频。想象一…...
EmbeddingGemma-300M效果实测:Ollama部署下的中文语义相似度
EmbeddingGemma-300M效果实测:Ollama部署下的中文语义相似度 1. 轻量级嵌入模型的实用价值 在当今信息爆炸的时代,文本数据的处理和分析变得愈发重要。无论是构建智能搜索系统、实现文档聚类,还是开发个性化推荐引擎,文本嵌入技…...
免费开源甘特图工具GanttProject:从任务混乱到清晰可视化的完整解决方案
免费开源甘特图工具GanttProject:从任务混乱到清晰可视化的完整解决方案 【免费下载链接】ganttproject Official GanttProject repository 项目地址: https://gitcode.com/gh_mirrors/ga/ganttproject 还在为项目管理中的任务混乱、进度模糊而烦恼吗&#x…...
OpenClaw+Qwen3.5-9B:科研党的文献综述加速器
OpenClawQwen3.5-9B:科研党的文献综述加速器 1. 为什么需要AI辅助文献处理 去年冬天,我在准备一篇关于量子计算在金融领域应用的综述论文时,遇到了所有科研人共同的噩梦:堆积如山的PDF文献。下载了87篇相关论文后,光…...
缺失值处理失效、类型推断崩塌、内存暴增…Polars 2.0清洗故障全解析,深度解读Arrow底层Schema约束机制
第一章:Polars 2.0数据清洗的核心挑战与演进脉络随着数据规模持续膨胀与实时分析需求激增,传统基于 Pandas 的数据清洗范式在内存效率、并行粒度和类型安全方面日益显露瓶颈。Polars 2.0 的发布并非简单功能叠加,而是以 Arrow-native 执行引擎…...
