【数据结构】JDK HashMap源码解析

news2024/11/24 5:29:02

目录

🌟HashMap源码解析

🌈类的属性

🌈构造方法

🌈put方法

🌟对比常用Map的子类实现:


🌟HashMap源码解析

        JDK8之前,HashMap就是数组+链表;

        JDK8之后,变成了数组+链表+红黑树。

问题1:什么时候会进行树化操作呢?

(1)当某个子链表的长度>=8并且整个哈希表的元素个数>=64时才会将当前的链表进行树化操作。

(2)若子链表的长度>=8但是哈希表的元素个数不满足大于等于64时,会进行整表扩容(也就是简单的将数组进行扩容)

        接下来我们主要从以下三部分来了解源码。

🌈类的属性

🌈构造方法

1、无参构造:只是初始化负载因子

  2、有参构造

(1)一个参数的有参构造

(2)两个参数的有参构造

         可以看见,在定义构造函数的时候,无论hi无参还是有参,这两种方式都并没有将数组容量进行初始化,那什么时候进行数组的初始化呢?我们接下来继续看。

🌈put方法(重点)

        HashMap最核心的代码就在于它的put方法。

问题2:请解释Object类的hashCode与equals的关系与区别?

  • equals类是判断两个对象的内容是否相同;
  • hashCode:默认的hashCode会将对象地址映射为整型,需要将任意数据类型转化Wie整型。

🆚区分:

(1)两个对象的hashCode返回相同的数值,equals是否返回true? 

        两个对象的hashCode虽然返回的数值相同,但是不同的数字经过哈希函数运算完全是有可能得到相同的索引值的,因此很有可能不是同一个对象,所以equals不一定相同;

(2)两个对象的equals方法返回true,hashCode是否返回相同的数值? 

        这其实也就是前文说到的哈希函数设计中的稳定性,一个相同的值经过哈希函数得到的值一定是相同的,因此两个对象是一样的,经过hashCode计算得到的值一定是相同的。

注意:若需要用到哈希方法,需要对默认的Object进行重写,因为我们需要使用对象的属性值来计算HashCode,而不是地址值。

        你分清了吗?😁 我们接下来继续看put方法~

 图太丑了🤣大家多看几遍理一理~通过上述,我们可以解决前文提出的问题:那就是数组容量是在第一次调用put方法时初始化的。这种现象叫做懒加载。我们顺便对put方法做一个小结~

🚨 put方法的核心流程小结:
(1)如果hashMap还没有初始化,就先进行哈希表的初始化操作(默认初始化容量是16)

(2)对传入的key值做哈希运算,得到要存放在数组中的索引位置

        如果此时还没有发生哈希碰撞,将该节点头插到数组中

        如果已经发生碰撞,判断此时是树还是链表形式:

                如果是链表形式,就将该节点作为链表的最后一个节点插入

                如果链表已经树化,就将该节点构造为树节点后再计入红黑树

(3)如果哈希表中存在key值,就只需要更新value值即可

(4)同时在更新元素个数的时候判断是否需要扩容。


🌟对比常用Map的子类实现:

TreeMapHashMap
内部数据结构RBTree哈希表
key和value是否可以为空

key:    ✅

value: ❎

        key必须具备可比较的性质或者传入比较器对象

key:    ✅

value: ✅

是否有序对于key“有序”,这个大小关系由Comparable或者比较器对象决定无序
是否线程安全不安全不安全

注意:若需要线程安全的Map集合,使用java.util.ConcurrentHashMap。


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

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

相关文章

基于C++/CLI实现C#与C++互调过程中的注意事项

目录 一、基于C/CLI 的调用原理二、注意事项如何基于VS2010完成C#调用C开发过程1、生成C应用程序(非托管代码)2、基于C/CLI生成托管代码3、C#调用 如何基于VS2010完成C调用C#开发过程 三、C/CLI与COM组件对比 一、基于C/CLI 的调用原理 C/CLI &#xff…

数据结构---队列的实现

文章目录 前言一、什么是队列?二、队列接口的实现 1.队列结构的定义2.接口实现总结 前言 队列是一种特殊的线性表。 特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作&a…

【Vue.js】1668- 初中级前端必须掌握的 10 个 Vue 优化技巧

优化 Vue.js 应用性能是每个前端开发人员都需要关注的问题。本文我将分享 10 个初中级前端必须掌握的 Vue.js 优化技巧,无论您是正在学习 Vue.js,还是已经在应用开发中使用它,希望这些技巧都会对你的工作有所帮助。 1. 优雅的设置 v-for 中的…

Java 中常见的 Exception 有哪些

Java 是一种广泛使用的编程语言,它的强大和流行程度在很大程度上归功于它的异常处理机制。异常是在程序执行期间出现的错误或意外情况。在 Java 中,异常是通过抛出和捕获异常对象来处理的。在本文中,我们将介绍 Java 中的一些常见异常类型及其…

浅堆深堆解读

浅堆(Shallow Heap) 浅堆是指一个对象所消耗的内存。在32位系统中,一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用8个字节。根据堆快照格式不同&#x…

【STM32】知识补充 深入探讨预分频器

【STM32】知识补充 深入探讨预分频器 概述分频器是什么工作原理计数器预分频器触发器预分频器模数计数器预分频器上升沿和下降沿 应用场景微控制器时钟预分频通信系统中的频率合成计时器与 PWM 波形生成数字电路设计中的同步与计时 预分频器实现方法硬件预分频器软件预分频器 案…

Swift之深入解析如何使用和自定义高级运算符

一、前言 在我之前的博客 Swift之深入解析如何自定义操作符 介绍了“基本运算符”,Swift 还提供了数种可以对数值进行复杂运算的高级运算符,它们包含了在 C 和 Objective-C 中已经被大家所熟知的位运算符和移位运算符。与 C 语言中的算术运算符不同&…

【flask】理解flask的几个难点,难啃的骨头,线程隔离啥的

1.三种路由和各自的比较 2.配置文件所有的字母必须大写 3.if __name__的作用 4.核心对象循环引用的几种解决方式–难 5.Flask的经典错误 6.上下文管理器 7.flask的多线程和线程隔离 三种路由 方法1:装饰器 python C#, java 都可以用这种方式 from flask import F…

SSM整合(三) | 异常处理器 - 项目异常的处理方案

文章目录 异常处理器异常处理器快速入门项目异常处理 异常处理器 异常处理器快速入门 程序开发过程中不可避免的会遇到异常现象 出现异常现象的常见位置与常见原因如下: 框架内部抛出的异常:因使用不规范导致 数据层抛出的异常:因外部服务器…

使用Statsmodel进行假设检验和线性回归

如果你使用 Python 处理数据,你可能听说过 statsmodel 库。Statsmodels 是一个 Python 模块,它提供各种统计模型和函数来探索、分析和可视化数据。该库广泛用于学术研究、金融和数据科学。在本文中,我们将介绍 statsmodel 库的基础知识、如何…

【技巧】Excel序号设置自动更新

做Excel表格的时候,我们经常需要设置序号,在输入序号的时候,你是不是这样做?手动输入序号1,再向下填充,当遇到有不想要的内容,点删除后,发现中间的序号就不连贯了,再手动…

二十五、OSPF高级技术——开销值、虚链路、邻居建立、LSA、多进程

文章目录 调试指令(三张表)1、邻居表:dis ospf peer brief2、拓扑表(链路状态数据库):dis ospf lsdb3、路由表:dis ip routing-table 一、OSPF 开销值/度量值(cost)1、co…

代码审计笔记之开篇

思想 代码审计是从软件测试发展而来,早起一般采用常规软件测试与渗透测试的手段来发现源码漏洞,但是随着软件规模的越来越大,架构越来越复杂,安全漏洞和后门也越来越多越来越隐蔽,这使得传统的软件测试方法很难检出源…

【Java入门合集】第二章Java语言基础(一)

【Java入门合集】第二章Java语言基础(一) 博主:命运之光 专栏JAVA入门 学习目标 掌握变量、常量、表达式的概念,数据类型及变量的定义方法; 掌握常用运算符的使用; 掌握程序的顺序结构、选择结构和循环结构…

C/C++每日一练(20230501)

目录 1. 对链表进行插入排序 🌟🌟 2. 找出小于平均值的数 ※ 3. 二叉树的最大深度 🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 对链表进行…

【五一创作】Apollo(入门)

Apollo(入门) Quick Start 配置中心是一种统一管理各种应用配置的基础服务组件 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且…

Springboot 实战一个依赖解决XSS攻击

1. 什么是XSS介绍 XSS: Cross Site Scripting,为不和层叠样式表(Cascading Style Sheets, CSS) 的缩写混淆,故将跨站脚本攻击缩写为XSS。 恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中 Web里面的Scrip…

【高并发】并发数据结构与多核编程

系列综述: 💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:材料主要源于多处理器编程的艺术进行的,每个知识点的修正和深入主要…

【JavaEE初阶】认识线程(Thread)

目录 🌾 前言 🌾 了解线程 🌈1.1 线程是什么? 🌈1.2 一些基本问题 🌾2、创建线程的方式 🌈 2.1 继承Thread类 🌈 2.2 实现Runnable接口并重写run()方法 🌈 注意…

有哪些好的学习方法?学霸们自己在用,却不愿意透露的

临近期末,很多家长都在跟我咨询,怎么才能提升孩子的学习效率? 原因就是,每天看着自己的孩子学习到深夜,但不少内容还是记不住, 学习和复习的效果非常的不理想。 今天,给大家分享的方法,是我自己一直也都在用的方法,效果非常的棒。 学长Ron,江苏某省重点高中毕业,高…