HashMap存入一个键值对的中间发生了什么(浅读源码)

news2024/9/24 7:14:12

存入键值对就是调用HashMap.put()过程(面试高频问题)

首先放出粗狂的总结

  1. 假如是Integer类型就会先查看IntegerCache中是否存在这个数字,有就从缓存中调用,没有则创建新的Integer对象(String类型没有这个过程,其他类型有待考究)

  1. 然后进入putValue方法,其中第一个参数是hash,进入hash()方法获得hash值,这里的hash()是每个类型不一样的,Integer的和String的都分别有各自的规则,Integer的就是对值进行与一个数异或,String的没考究

  1. hash结束后,putValue就先创建各种成员变量,主要就是Node<K,V>数组,这个数组的初始化要调用resize()函数,初始化的话通常就是直接给个16大小的Node[]

  1. resize结束后就创建一个Node对象,将key、value、hash都存进去,然后把这个Node存进Node数组中,put就宣告完成了。

我们对下列代码进行调试看看

public static void main(String[] args) {
    HashMap<Integer, String> hashMap = new HashMap<>();
    hashMap.put(3, "String");
}

因为key是Integer类型,所以先进入Integer的valueOf进行类型检查?

假如在IntegerCache范围内的数就直接调用IntegerCache。

查看IntegerCache源码可以发现,IntegerCache的low是-128,high默认是127?也可以自定义为127内的数

至于这里为什么是i + (-low),暂时还是先不研究吧,反正最终的key值也是3

接着是正式进入了put函数(所以说之前要做的是对key进行类型检查(不知道是不是只对Integer这样?好像是的,后来将Key改成了String类型,没发现有类似的方法调用))

put又调用了putValue方法,里面有一个hash的函数

假如key不为null的话就进入hash函数得到哈希值

这里使用的哈希方法为获得key的hashCode然后进行16位移后的按位异或

key这里是Object类型,可能每个Object都有自己的hashCode吧 都是重写得来的,Integer的hashCode就比较简单,直接返回数字本身了

然后就正式进入了putVal函数

函数伊始就是创建各种变量和变量类

这里两个重点,一个是Node类

一个是resize方法

我们先来大概看一下Node类,Node也是个存储键值对的类,实现了Map.Entry接口

Map是一个接口,Entry也是。他们分别都具有什么要素?

大概可以理解为,Map的方法中更多是针对键值对是,是整体的宏观的。比如size是键值对的个数,isEmpty是有没有键值对,put是存入整一个键值对。(contains方法好像比较难解释了就…)

Entry的方法则更多是单独针对键或者值的,比如getKey就是拿到一个key,getValue就是拿到一个value,他们都是独立的,没有方法是针对键值对进行操作的。

Node,作为实现Entry的类,所以其方法也是但对针对键或者值的。自己的元素就是基本成员变量如哈希值、key、value、下一个节点的引用(这里也能体现出其链表形式的数据结构)。

resize的代码较多,这里就不贴上源码了,大概的功能就是:

  1. 假如是创建行为,就给一个初始化的Node<K,V> []数组,这个数组的初始化大小是16(对比ArrayList初始化的数组空间大小为10)

  1. 假如是扩容行为,就会进行对threshold和size的比较,这个threshold就是当前Node[]的占有率(关联负载因子,默认0.75),如有需要就进行扩容,没有就不变吧。

因为我的运行代码较短,put后直接就结束了main线程,可以看到还调用了exit方法,方法的内容大概就是结束线程,释放资源这样,这里应该和put是没什么关系的吧?属于题外话。

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

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

相关文章

【JavaSE】复习(进阶)

文章目录1.final关键字2.常量3.抽象类3.1概括3.2 抽象方法4. 接口4.1 接口在开发中的作用4.2类型和类型之间的关系4.3抽象类和接口的区别5.包机制和import5.1 包机制5.2 import6.访问控制权限7.Object7.1 toString()7.2 equals()7.3 String类重写了toString和equals8.内部类8.1…

【谷粒学院】vue、axios、element-ui、node.js(44~58)

44.前端技术-vue入门 &#x1f9e8;Vue.js 是什么 Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。 Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或既有项目整合。另一方面&#xff0c;当与现代化的工具…

RK3568编译Android11和目录讲解

文章目录 前言一、下载android11源码二、环境搭建1.增加交换内存三、编译瑞芯微原厂源码四、目录讲解总结前言 本文记录在Ubuntu18.04中编译Android11,只有编译了源码,后面才能进行驱动的开发,有兴趣的小伙伴可以和我一起学习吧! 提示:以下是本篇文章正文内容,下面案例可…

@Value注解的使用(可用于配置文件)

基本概念Value&#xff1a;注入配置文件中的内容。只要是spring的注解类&#xff08;service,compotent, dao等&#xff09;中都可以。Component&#xff1a;泛指组件&#xff0c;当组件不好归类的时候&#xff0c;可以使用这个注解进行标注。AutoWired&#xff1a;自动导入依赖…

【JAVA程序设计】(C00104)基于Springboot的家庭理财管理系统——有文档

基于Springboot的家庭理财管理系统项目简介项目获取开发环境项目技术运行截图运行视频项目简介 基于Springboot开发的家庭理财管理系统设计与实现共分为三个角色&#xff1a;系统管理员、家庭管理员、家庭用户 管理员角色包含以下功能&#xff1a; 用户管理、修改密码、角色管…

【C++】map和set用法详解

文章目录1.关联式容器2.键值对3.树形结构的关联式容器3.1 set3.1.1 set的介绍3.1.2 set的模板参数列表3.1.3 set的使用3.2 mapmap的介绍map的模板参数列表map的使用关于map的元素访问总结3.3multimap1.关联式容器 我们接触过STL中的部分容器&#xff0c;比如&#xff1a;vecto…

2 k-近邻算法

0 问题引入 想一想&#xff1a;下面图片中有三种豆&#xff0c;其中三颗豆品种未知&#xff0c;如何判断他们类型&#xff1f; 1 KNN概述 1.1 KNN场景 电影可以按照题材分类&#xff0c;那么如何区分 动作片 和 爱情片 呢&#xff1f; 动作片&#xff1a;打斗次数更多爱情…

【蓝牙mesh】Lower协议层介绍

【蓝牙mesh】Lower协议层介绍 Lower层简介 Lower协议层用于处理网络层以下的功能&#xff0c;包括节点的广播、重传、路由和网络拓扑等&#xff0c;是实现蓝牙mesh网络的关键协议之一。其中Lower协议层中最主要的一部分工作就是mesh数据的分片和组包。 Lower层是将Upper层发过…

buu [GWCTF 2019]BabyRSA 1

题目描述&#xff1a; import hashlib import sympy from Crypto.Util.number import *flag GWHT{******} secret ******assert(len(flag) 38)half len(flag) / 2flag1 flag[:half] flag2 flag[half:]secret_num getPrime(1024) * bytes_to_long(secret)p sympy.nextp…

【MySQL】事务隔离级别是怎么实现的?

事务隔离级别是怎么实现的&#xff1f; 四种隔离级别具体的实现方式 对于「读未提交」&#xff1a;直接读取最新的数据就好。对于「串行化」&#xff1a;通过加读写锁的方式来避免并行访问。对于「读提交」和「可重复读」&#xff1a;通过 Read View 来实现&#xff0c;主要区…

JS学习第4天——事件高级(注册/删除事件、DOM事件流、阻止事件冒泡、事件委托、常用的鼠标/键盘事件)

目录一、注册事件 / 删除事件1、注册事件&#xff08;绑定事件&#xff09;2、删除事件&#xff08;解绑事件&#xff09;二、DOM事件流三、事件对象event1、事件对象的兼容性2、e.targent和this的区别3、事件对象常见的属性和方法四、阻止事件冒泡五、事件委托&#xff08;代理…

数据采集与预处理学习

文章目录要求题解要求 根据表格求出哪两个演员合作电影数最多&#xff0c;及合作的电影数。 题解 from openpyxl import load_workbookwb load_workbook("电影导演演员信息表.xlsx") ws wb.worksheets[0]actors_films dict() for i, row in enumerate(ws.rows):i…

CAN总线开发一本全(4) - FlexCAN的驱动程序

CAN总线开发一本全&#xff08;4&#xff09; - FlexCAN的驱动程序 苏勇&#xff0c;2023年2月 文章目录CAN总线开发一本全&#xff08;4&#xff09; - FlexCAN的驱动程序引言从MindSDK获取FlexCAN驱动程序数据结构配置通信引擎的结构体类型访问MB的结构体类型配置ID过滤器的…

1 机器学习基础

1 机器学习概述 1.1 数据驱动的问题求解 大数据-Big Data 大数据的多面性 1.2 数据分析 机器学习&#xff1a;海量的数据&#xff0c;获取有用的信息 专门研究计算机怎样模拟或实现人类的学习行为&#xff0c;以获取新的知识或技能&#xff0c;重新组织已有的知识结构使之…

Python多进程编程

一 多进程编程 Python实现多进程的方式有两种&#xff1a;一种方法是os模块中的fork方法&#xff0c;另一种是使用multiprocessing模块。 前者仅适用于LINUX/UNIX操作系统&#xff0c;对Windows不支持&#xff0c;后者则是跨平台的实现方式。 第一种方式&#xff1a;使用os模…

【C++修行之路】STL——模拟实现string类

文章目录前言类框架构造与析构c_str迭代器操作符重载[]&#xff1a;&#xff1a;> > < < !:reverse与resizereverseresizepush_back与append复用实现insert和erasec_str与流插入、流提取eraseswap(s1,s2)与s1.swap(s2)结语前言 这次我们分几个部分来实现string类…

spark第一章:环境安装

系列文章目录 spark第一章&#xff1a;环境安装 文章目录系列文章目录前言一、文件准备1.文件上传2.文件解压3.修改配置4.启动环境二、历史服务器1.修改配置2.启动历史服务器总结前言 spark在大数据环境的重要程度就不必细说了&#xff0c;直接开始吧。 一、文件准备 1.文件…

React Use Hook 尝鲜

React Use Hook 尝鲜 最近继续在找处理 React 异步调用的方式……主要是现在需求比较复杂&#xff0c;用 cache query 的方式去实现有那么一丢丢的麻烦&#xff0c;又不是很想用额外的包&#xff0c;所以就想看看有没有比较好的一些处理方式。 当然&#xff0c;可以用到生产环…

tkinter界面的TCP通信/tkinter开启线程接收TCP

前言 用简洁的语言写一个可以与TCP客户端实时通信的界面。之前做了一个项目是要与PLC进行信息交互的界面&#xff0c;在测试的时候就利用TCP客户端来实验&#xff0c;文末会附上TCP客户端。本文分为三部分&#xff0c;第一部分是在界面向TCP发送数据&#xff0c;第二部分是接收…

Linux基础命令-dd拷贝、转换文件

文章目录 dd 命令介绍 语法格式 基本参数 参考实例 1&#xff09;生成一个200M的新文件 2&#xff09;拷贝文件的100个字节 3&#xff09;将文件的字母全部转换成大写 4&#xff09;将linux自带的光盘制作成iso格式的镜像文件 5&#xff09;使用dd命令制作1G的交换分…