Hashmap源码

目录

HashMap底层原理

JDK1.8及以后底层结构为:数组+链表+红黑树

默认参数

扩容机制

数组

链表

红黑树

HashMap为什么用红黑树不用B树

HashMap什么时候扩容

HashMap的长度为什么是 2的 N 次方


HashMap底层原理

JDK1.8及以后底层结构为:数组+链表+红黑树

HashMap是Java集合框架中一种基于哈希表实现的Map接口,它存储键值对,键是唯一的,而值可以重复。它的底层结构是一个数组结构,在实际情况中,这个数组被分为多个“桶(bucket)”,每个桶内存储的是链表或红黑树(JDK1.8中引入),具体使用哪种取决于链表的长度和当前Map的大小

  • 默认参数

    • 默认负载因子(load factor):0.75。负载因子是衡量HashMap满的程度的一个标准。当HashMap中的元素数量达到容量与负载因子的乘积时,就会进行扩容。

    • 默认容量(capacity):16,必须是2的幂。

  • 扩容机制

    • 当HashMap中的元素数量达到threshold时,即当前容量乘以负载因子,HashMap会进行扩容操作。

    • 扩容操作会创建一个新的数组,其大小为原数组大小的两倍,并重新计算每个键的哈希值和在新数组中的位置。

    • 这个过程涉及到重新计算每个键的哈希值,并将所有的键值对重新插入到新的数组中,因此扩容是一个比较耗费性能的操作。

  • 数组

    • 作用:数组是HashMap存储元素的主要结构,每个数组元素是一个桶(bucket),可以存储一个或多个键值对(Entry)。

    • 默认大小:默认初始容量为16(必须是2的幂)。

    • 扩容机制:当HashMap中的元素数量达到容量与负载因子乘积时,即size >= threshold(threshold = capacity * load factor),数组会进行扩容操作,扩容为原来的两倍大小。

对于默认的容量和负载因子,threshold 的默认值是:
threshold = 16 * 0.75 = 12
这意味着当 HashMap 中的元素数量达到 12 时,HashMap 会进行扩容操作。扩容后的新容量是原容量的两倍为36,同时 threshold 也会相应地更新为新的容量乘以负载因子。
  • 链表

    • 作用:当数组的同一个桶位置(即索引相同)发生哈希碰撞时,多个键值对会以链表的形式存储。JDK 1.8之前,HashMap就是使用链表处理冲突;JDK 1.8之后,当链表长度大于一定阈值时,链表会转换为红黑树。

    • 默认阈值:链表转红黑树的阈值为8(当链表长度大于8时,会转换为红黑树)。

  • 红黑树

    • 作用:为了提高HashMap的性能,当链表长度过长时,链表会被转换成红黑树。这样可以减少搜索时间,从O(n)降低到O(log n)。

    • 默认阈值:链表转回链表的阈值为6(当红黑树中的节点数量小于6时,会转换回链表)。

HashMap为什么用红黑树不用B树

HashMap 使用红黑树(Red-Black Tree)而不是 B 树的主要原因是效率和复杂度。

  • 效率:红黑树相对于 B 树,在插入、删除和查找操作上具有更好的平均性能。红黑树的平衡性质可以保证树的高度相对较小,从而减少了搜索的路径长度,提高了操作的效率。

  • 复杂度:B 树是一种多路搜索树,节点可以包含多个关键字和指针,适合用于磁盘存储等场景,可优化磁盘 IO 操作。然而,在内存中的数据结构中,红黑树的实现更为简单,代码的复杂度较低。同时,红黑树的性能在典型的 HashMap 使用场景中通常表现出良好的性能。

另外,HashMap 维护了一个哈希表和一个链表或红黑树的混合结构(JDK8 之后),当发生哈希冲突时,会使用链表或红黑树来处理冲突。链表适合处理冲突较少的情况,而红黑树则适合处理冲突较多的情况。红黑树相对于链表具有更高的查找效率,因此在冲突较多的情况下能够提供更好的性能。

总之,HashMap 使用红黑树而不是 B 树主要是出于对效率和复杂度的考虑。红黑树在内存中的实现更简单,对于典型的 HashMap 使用场景能够提供良好的性能,且适用于处理冲突较多的情况。


最简回答:HashMap使用红黑树而不是B树,是因为红黑树相对于B树在插入、删除和查找等操作上的平衡性能更好,且红黑树的节点比B树的节点更小,占用的内存更少,适合存储在内存中的数据结构。

HashMap什么时候扩容

  • 在JDK1.7中,当HashMap中元素数量超过当前容量与负载因子(默认为0.75)的乘积时,会触发扩容操作,扩容后的容量为当前容量的两倍。例如,初始容量为16,当元素数量达到12时会触发扩容,扩容后的容量为32。

  • 在JDK 1.8中,HashMap的扩容和红黑树转换是两个独立的操作,且顺序是先扩容,然后再进行红黑树的转换。当HashMap中的元素数量超过负载因子(默认为0.75)与数组容量的乘积时,会触发扩容操作。扩容会重新调整数组的大小,并将原来数组中的元素重新分配到新的数组位置上。扩容操作会导致原本哈希冲突较多的链表长度变长,因此当链表长度超过阈值(默认为8)时,会将链表转化为红黑树。综上所述,在JDK 1.8中,HashMap的操作顺序是先扩容,然后再进行红黑树的转换。扩容是为了减少哈希冲突,提高HashMap的性能和效率,而链表转红黑树的操作则是为了在特定情况下提供更好的查找、插入和删除元素的性能。

HashMap的长度为什么是 2的 N 次方

为了能让 HashMap 存数据和取数据的效率高,尽可能地减少 hash 值的碰撞,也就是说尽量把数

据能均匀的分配,每个链表或者红黑树长度尽量相等。我们首先可能会想到 % 取模的操作来实现。

下面是回答的重点哟:

取余(%)操作中如果除数是 2 的幂次,则等价于与其除数减一的与(&)操作(也就是说hash % length == hash &(length - 1) 的前提是 length 是 2 的 n 次方)。并且,采用二进制位操作 & ,相对于 % 能够提高运算效率。

这就是为什么 HashMap 的长度需要 2 的 N 次方了


最简回答:HashMap的长度选择为2的N次方是为了提高散列算法的效率和分布均匀性,通过使用2的幂次方作为长度,可以确保哈希码的高位和低位可以均匀参与到散列计算中,减少哈希冲突的发生,并提高散列算法的效率和性能。

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

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

相关文章

【JAVA 字符串常量池、new String的存储机制、==与equals的区别,以及字符串重新赋值时的指向变化】

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录系列文章目录代码原理解错误逻辑理解理解与修正&#xff1a…

博客项目 Spring + Redis + Mysql

基础模块1. 邮箱发送功能最初设计的接口 (雏形)public interface EmailService {/*** 发送验证码邮件** param email 目标邮箱* return 发送的code* throws RuntimeException 如果发送邮件失败,将抛出异常*/String sendVerificationCode(Stri…

前端处理导出PDF。Vue导出pdf

前言:该篇主要是解决一些简单的页面内容导出为PDF1.安装依赖使用到两个依赖,项目目录下运行这两个//页面转换成图片 npm install --save html2canvas //图片转换成pdf npm install jspdf --save 2.创建通用工具类exportPdf.js文件可以保存在工具类目录下…

【GM3568JHF】FPGA+ARM异构开发板烧录指南

1. Windows烧录说明 SDK 提供 Windows 烧写工具(工具版本需要 V3.31或以上),工具位于工程根目录: tools/ ├── windows/RKDevTool 如下图,编译生成相应的固件后,设备烧写需要进入 MASKROM 或 LOADER 烧写模式,准备…

C++ 多进程编程深度解析【C++进阶每日一学】

文章目录一、引言二、核心概念:进程 (Process)功能与作用三、C 多进程的实现方式四、核心函数详解1. fork() - 创建子进程函数原型功能说明返回值完整使用格式2. wait() 和 waitpid() - 等待子进程结束函数原型参数与返回值详解3. exec 系列函数 - 执行新程序函数族…

一周学会Matplotlib3 Python 数据可视化-绘制面积图(Area)

锋哥原创的Matplotlib3 Python数据可视化视频教程: 2026版 Matplotlib3 Python 数据可视化 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程讲解利用python进行数据可视化 科研绘图-Matplotlib,学习Matplotlib图形参数基本设置&…

北京JAVA基础面试30天打卡11

1.索引创建注意事项 适合的场景 1.频繁使用where语句查询的字段 2.关联字段需要建立索 3.如果不创建索引,那么在连接的过程中,每个值都会进行一次全表扫描 4.分组和排序字段可以建立索引因为索引天生就是有序的,在分组和排序时优势不言而喻 5…

vscode无法检测到typescript环境解决办法

有一个vitereacttypescript项目,在工作电脑上一切正常。但是,在我家里的电脑运行,始终无法检测到typescript环境。即使出现错误的ts语法,也不会有报错提示,效果如下:我故意将一个string类型,传入…

【MCP开发】Nodejs+Typescript+pnpm+Studio搭建Mcp服务

MCP服务支持两种协议,Studio和SSE/HTTP,目前官方提供的SDK有各种语言。 开发方式有以下几种: 编程语言MCP命令协议发布方式PythonuvxSTUDIOpypiPython远程调用SSE服务器部署NodejspnpmSTUDIOpnpmNodejs远程调用SSE服务器部署… 一、初始化项…

vscode使用keil5出现变量跳转不了和搜索全局不了

vscode使用keil5出现变量跳转不了,或者未包含文件,或者未全局检索; 参考如下文章后还会出现; 为什么vscode搜索栏只搜索已经打开的文件_vscode全局搜索只能搜当前文件-CSDN博客 在机缘巧合之下发现如下解决方式: 下载…

命名空间——网络(net)

命名空间——网络(net) 一、网络命名空间:每个都是独立的“网络房间” 想象你的电脑是一栋大楼,每个网络命名空间就是大楼里的一个“独立房间”: 每个房间里有自己的“网线接口”(网卡)、“门牌…

一文读懂16英寸笔记本的实际尺寸与最佳应用场景

当您搜索"16寸笔记本电脑长宽"时,内心真正在问的是什么?是背包能否容纳?桌面空间是否足够?还是期待屏幕尺寸与便携性的完美平衡?这个看似简单的尺寸数字背后,凝结着计算机制造商对用户体验的深刻…

Android Studio中创建Git分支

做一些Android项目时,有时候想要做一些实验性的修改,这个实验可能需要很多步骤,所以不是一时半会能完成的,这就需要在实验的过程中不断修改代码,且要提交代码,方便回滚或比较差异,但是既然是实验…

内存可见性和伪共享问题

文章目录什么是内存可见性问题为什么会出现可见性问题解决可见性问题的方法1. 使用volatile关键字2. 使用synchronized3. 使用java.util.concurrent包下的原子类什么是伪共享问题CPU缓存行伪共享的危害解决伪共享的方法1. 缓存行填充2. 使用Contended注解(JDK 8&…

Spring MVC 九大组件源码深度剖析(三):ThemeResolver - 动态换肤的奥秘

文章目录一、主题机制的核心价值二、核心接口设计三、四大实现类源码解析1. FixedThemeResolver(固定主题策略)2. CookieThemeResolver(Cookie存储策略)3. SessionThemeResolver(Session存储策略)4. Abstra…

一、Docker本地安装

((这里引用知乎上大佬的说法:https://www.zhihu.com/question/48174633 服务器虚拟化解决的核心问题是资源调配,而容器解决的核心问题是应用开发、测试和部署。 一、参考帖子 Ubuntu 的 |Docker 文档 【docker】ubuntu完全卸载docker及再次安装_ubuntu…

LeetCode 分类刷题:2962. 统计最大元素出现至少 K 次的子数组

题目给你一个整数数组 nums 和一个 正整数 k 。请你统计有多少满足 「 nums 中的 最大 元素」至少出现 k 次的子数组,并返回满足这一条件的子数组的数目。子数组是数组中的一个连续元素序列。示例 1:输入:nums [1,3,2,3,3], k 2 输出&#…

10分钟掌握swift

整理一个 10分钟掌握 Swift 的精华指南,用一个 Demo 串联 Swift 的核心语法、数据结构、函数、类/结构体和闭包,让你快速入门。1️⃣ 基础语法与变量import Foundation // 引入基础库// 变量和常量 var name: String "Alice" // 可变 let…

【完整源码+数据集+部署教程】食品分类与实例分割系统源码和数据集:改进yolo11-AggregatedAttention

背景意义 研究背景与意义 随着全球食品产业的快速发展,食品安全和质量控制日益成为社会关注的焦点。食品分类与实例分割技术的应用,能够有效提升食品识别的准确性和效率,为食品监管、营养分析以及智能餐饮等领域提供重要支持。传统的食品识别…

C# 中的N+1问题

目录 含义 影响 避免方法 1. 立即加载(Eager Loading) 2. 显式加载(Explicit Loading) 3. 投影(Projection) 4. 批处理查询 5. 禁用延迟加载 含义 N1 问题 是 ORM(对象关系映射&#x…