谈谈我对HashMap扩容机制的理解及底层实现

目录

一、HashMap的底层实现

二、HashMap扩容机制

概念

详细扩容:

1、初始容量

2、添加元素

3、元素数量检查

4、触发扩容

5、迁移元素

6、更新容量和阈值

代码:


一、HashMap的底层实现

HashMap 是 Java 中常用的数据结构之一,用于存储键值对。它的底层实现是基于哈希表(Hash Table)。以下是 HashMap 的底层实现细节:

  1. 数组: HashMap 内部维护一个数组,数组的每个元素称为桶(bucket)。数组的长度通常是2的幂,这是为了便于哈希函数计算索引值。

  2. 链表和红黑树: 在每个桶中,如果发生哈希冲突(即两个不同的键具有相同的哈希值),那么这些键值对会以链表的形式存储在同一个桶中。从Java 8 开始,当链表的长度超过一定阈值时,会将链表转换为红黑树,以提高查询性能。

  3. 哈希函数: HashMap 使用键的哈希码来计算索引值。哈希码是通过调用键的 hashCode() 方法得到的。计算索引值的过程涉及到取模运算,即 index = hashCode % arrayLength

  4. 扩容:HashMap 中的元素个数超过了容量与负载因子的乘积时,就会触发扩容操作。负载因子是一个表示填充程度的浮点数,默认为0.75。扩容时,数组的长度会变为原来的两倍,并且原来的键值对需要重新计算哈希码和索引值,然后放入新的数组中。

  5. 并发性: HashMap 在多线程环境下是不安全的,因为多个线程可能同时修改 HashMap,导致数据不一致。在Java 8及之后的版本中,提供了 ConcurrentHashMap 来解决这个问题,它通过分段锁和 CAS 操作来保证并发安全性。

参考资料

HashMap 源码 、TreeBin 类(红黑树容器)

二、HashMap扩容机制

概念

HashMap 的扩容是为了保持其在负载因子(load factor)范围内的性能。负载因子是一个表示填充程度的浮点数,默认值为 0.75。当 HashMap 中的元素数量达到容量与负载因子的乘积时,就会触发扩容操作。

详细扩容:

1、初始容量

当创建一个新的 HashMap 时,它会有一个初始容量,通常是16。这个初始容量可以在构造函数中指定,但如果不指定,默认值为16。

2、添加元素

当往 HashMap 中添加键值对时,首先计算键的哈希码,并根据哈希码计算索引值。如果该索引位置没有元素,直接插入;如果有元素,发生哈希冲突,就会以链表的形式添加到相应的桶中。

3、元素数量检查

在每次添加元素后,HashMap 会检查当前元素的数量是否超过了容量与负载因子的乘积,即 size > threshold = capacity * loadFactor

4、触发扩容

如果元素数量超过了阈值,就会触发扩容操作。扩容时,HashMap 将会创建一个新的数组,长度是原数组的两倍(newCapacity = oldCapacity * 2),然后将原数组中的元素重新计算哈希码和索引值,放入新数组中。

5、迁移元素

扩容后,原数组中的每个桶可能包含一个链表或一棵红黑树。HashMap 将遍历原数组中的每个桶,然后将其中的元素迁移到新数组中。在迁移的过程中,由于新数组长度是原数组长度的两倍,因此每个元素的索引值可能会发生变化。

6、更新容量和阈值

扩容后,HashMap 更新自己的容量和阈值。容量变为新数组的长度,阈值变为新容量与负载因子的乘积。

代码:

import java.util.Arrays;
import java.util.LinkedList;public class MyHashMap<K, V> {private static final int DEFAULT_INITIAL_CAPACITY = 16;private static final float DEFAULT_LOAD_FACTOR = 0.75f;private Node<K, V>[] table;private int size;private int threshold;@SuppressWarnings("unchecked")public MyHashMap() {table = new Node[DEFAULT_INITIAL_CAPACITY];threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);}public void put(K key, V value) {if (key == null) {throw new IllegalArgumentException("Key cannot be null");}if (size + 1 > threshold) {resize();}int hash = hash(key);int index = getIndex(hash, table.length);if (table[index] == null) {table[index] = new Node<>(hash, key, value);size++;} else {LinkedList<Node<K, V>> bucket = table[index].getBucket();for (Node<K, V> node : bucket) {if (node.key.equals(key)) {// Key already exists, update the valuenode.value = value;return;}}// Key does not exist in the bucket, add a new nodebucket.add(new Node<>(hash, key, value));size++;}}private void resize() {int oldCapacity = table.length;int newCapacity = oldCapacity * 2;threshold = (int) (newCapacity * DEFAULT_LOAD_FACTOR);Node<K, V>[] newTable = new Node[newCapacity];for (Node<K, V> node : table) {if (node != null) {LinkedList<Node<K, V>> bucket = node.getBucket();for (Node<K, V> entry : bucket) {int hash = hash(entry.key);int index = getIndex(hash, newCapacity);if (newTable[index] == null) {newTable[index] = new Node<>(hash, entry.key, entry.value);} else {newTable[index].getBucket().add(new Node<>(hash, entry.key, entry.value));}}}}table = newTable;}private int hash(K key) {// Simplified hash function for illustration purposesreturn key.hashCode();}private int getIndex(int hash, int length) {// Simplified index calculation for illustration purposesreturn hash % length;}private static class Node<K, V> {private final int hash;private final K key;private V value;private LinkedList<Node<K, V>> bucket;public Node(int hash, K key, V value) {this.hash = hash;this.key = key;this.value = value;this.bucket = new LinkedList<>();this.bucket.add(this);}public LinkedList<Node<K, V>> getBucket() {return bucket;}}public static void main(String[] args) {MyHashMap<String, Integer> myHashMap = new MyHashMap<>();myHashMap.put("One", 1);myHashMap.put("Two", 2);myHashMap.put("Three", 3);// ... (additional testing and usage)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/202089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python学习路线 - Python语言基础入门 - 判断语句

Python学习路线 - Python语言基础入门 - 判断语句 前言布尔类型和比较运算符布尔类型布尔类型的定义 比较运算符 if语句的基本格式if判断语句 if else 语句if elif else 语句判断语句的嵌套实战案例 前言 进行逻辑判断&#xff0c;是生活中常见的行为。同样&#xff0c;在程序…

Powerbuilder9.0 安装是一直卡在setup is running无法继续

这种情况是安装时&#xff0c;他后面弹出来一个提示框&#xff0c;但是因为其他进程的干扰&#xff0c;我们无法看到也就无法继续了。 我看到这个文章&#xff1a;https://blog.csdn.net/FLORY_/article/details/105244102 使用他说的方法的确有效。过程 1. 打开任务管理器 …

子查询在SQL中的应用和实践

作者&#xff1a;CSDN-川川菜鸟 在SQL中&#xff0c;子查询是一种强大的工具&#xff0c;用于解决复杂的数据查询问题。本文将深入探讨子查询的概念、类型、规则&#xff0c;并通过具体案例展示其在实际应用中的用途。 文章目录 子查询概念子查询的类型子查询的规则实际案例分析…

Photoshop Elements 2023 v21.0(ps简化版)

Photoshop Elements 2023是一款ps简化版图像处理软件&#xff0c;它加入了一些新的功能和工具&#xff0c;以帮助用户更高效地处理图片。 新功能&#xff1a;软件加入了黑科技&#xff0c;采用Adobe Sensei AI技术&#xff0c;主打人工智能&#xff0c;一键P图&#xff0c;新增…

Demystifying DeFi MEV Activities in Flashbots Bundle

目录 笔记后续的研究方向摘要引言贡献 Demystifying DeFi MEV Activities in Flashbots Bundle CCS 2023 笔记 本文介绍了对 Flashbots 捆绑包中的去中心化金融 &#xff08;DeFi&#xff09; 矿工可提取价值 &#xff08;MEV&#xff09; 活动的研究。作者开发了ActLifter&am…

文献速递:多模态影像组学文献分享(一种诊断方法结合了多模态放射组学和基于腰椎CT及X光的机器学习模型,用于骨质疏松症)

文献速递&#xff1a;多模态影像组学文献分享:(一种诊断方法结合了多模态放射组学和基于腰椎CT及X光的机器学习模型&#xff0c;用于骨质疏松症)** Title 题目 A diagnostic approach integrated multimodal radiomics with machine learning models based on lumbar spine CT…

Codeforces Round 913 (Div. 3) A~E

目录 A. Rook 问题分析: B. YetnotherrokenKeoard 问题分析: C. Removal of Unattractive Pairs 问题分析: D. Jumping Through Segments 问题分析: E. Good Triples 问题分析: A. Rook 问题分析: 给一个棋子将其同行同列的位置输出 #include<bits/s…

❀My学习Linux命令小记录(14)❀

目录 ❀My学习Linux命令小记录&#xff08;14&#xff09;❀ 56.man指令 57.whatis指令 58.info指令 59.--help指令 60.uname指令 ❀My学习Linux命令小记录&#xff08;14&#xff09;❀ 56.man指令 功能说明&#xff1a;查看Linux中的指令帮助。 &#xff08;ps.man命…

上门预约洗鞋店小程序

互联网洗鞋店小程序开发&#xff0c;结合洗鞋行业线下实际运营情况和经验&#xff0c;专为洗鞋人、洗鞋店打造的高效、实用、有价值的洗鞋私域流量管理软件系统。 帮助洗鞋人建立自己的私域流量&#xff0c;实现会员用户管理&#xff0c;用户与商家点对点互联互通&#xff0c;提…

工业级路由器在智能交通系统(ITS)中的创新应用

智能交通系统&#xff08;ITS&#xff09;作为一种先进的交通管理与控制系统&#xff0c;旨在提高交通运输系统的效率、安全性和便捷性。随着科技的不断发展&#xff0c;智能交通系统已经成为城市交通管理的重要组成部分。而工业级路由器作为一种可靠的网络通信设备&#xff0c…

使用Python内置库实现数据的加密与校验

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 数据的安全性是现代应用程序中不可忽视的一个重要方面。在Python中&#xff0c;我们可以利用内置的加密和校验库来保护敏感信息。本文将深入讨论如何使用Python内置库实现数据的加密和校验&#xff0c;为开发者提…

SQL Server 数据库,创建数据库并使用索引查询学员考试成绩

5.1索引 索引提供指针以指向存储在表中指定列的数据值&#xff0c;然后根据指定的次序排列这些指针&#xff0c;再跟随 指针到达包含该值的行。 5.1.1什么是索引 数据库中的索引与书籍中的目录类似。在一本书中&#xff0c;无须阅读整本书&#xff0c;利用目录就可以快速查 找…

『App自动化测试之Appium基础篇』| 从定义、原理、环境搭建、安装问题排查等深入了解Appium

『App自动化测试之Appium基础篇』| 从定义、原理、环境搭建、安装问题排查等深入了解Appium 1 关于Android UI自动化测试2 Appium简介3 Appium原理3.1 Android端过程3.2 iOS端过程 4 补充内容5 JDK下载6 JDK配置7 SDK下载8 SDK配置9 配置Android环境10 安装NodeJs11 解决node安…

今天刷basic

一 在kali里边链接这个服务器 ssh -p 25199 rootnode4.buuoj.cn 然后回车 yes 输入密码123456 ls查看发现什么都没有&#xff0c;cd ..返回上一级目录 ls 发现有flag.txt 查看文件得到flag flag{477f20d3-acd3-46e1-b50a-633e58b769c7}

Python中读写(解析)JSON文件的深入探究

目录 一、引言 二、如何读取JSON文件 三、如何写入JSON文件 四、如何解析JSON字符串 五、错误处理和异常处理 六、使用第三方库提高效率 七、总结 一、引言 在Python中&#xff0c;我们经常使用JSON&#xff08;JavaScript Object Notation&#xff09;格式来存储和传输…

计算机速成课Crash Course - 08. 指令和程序

今天开始计算机速成课Crash Course的系列讲解。 更多技术文章&#xff0c;全网首发公众号 “摸鱼IT” 锁定 -上午11点 - &#xff0c;感谢大家关注、转发、点赞&#xff01; 计算机速成课Crash Course - 08. 指令和程序 08. 指令和程序 上集我们把 ALU, 控制单元, RAM, 时钟…

基于Java SSM框架实现超市进销存购物商城管理系统项目【项目源码+论文说明】

基于java的SSM框架实现超市进销存购物商城管理系统演示 摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;社区生活超市管理系统当然也不能排除在外。社区生活超市管理系统…

【QT】容器类的迭代

迭代器(iterator)为访问容器类里的数据项提供了统一的方法&#xff0c;Qt有两种迭代器类&#xff1a;Java类型的迭代器和STL类型的迭代器。 Java类型的迭代器更易于使用&#xff0c;且提供一些高级功能&#xff0c;而STL类型的迭代器效率更高。 Qt还提供一个关键字foreach&…

ORACLE使用Mybatis-plus批量插入

ORACLE使用mybatis-plus自带的iservice.saveBatch方法时&#xff0c;会报DML Returing cannot be batch错误&#xff1a; 推测原因是oracle不支持insert into table_name (,) values &#xff08;&#xff0c;&#xff09;,&#xff08;&#xff09;的写法。且oracle不会自动生…

华为Watch Buds手表耳机声音小怎么办?试试这些方法

使用华为 WATCH Buds 的手表耳机的铁子们&#xff0c;你们有没有和我遇到同样的问题&#xff1a;刚用的时候音质超级好&#xff0c;但是用了一段时间后&#xff0c;偶尔会遇到耳机声音变小&#xff0c;甚至出现左右耳音量不一致的情况。 如果有的话&#xff0c;不用担心&#…