map源码分析

news/2024/4/25 19:00:24/文章来源:https://blog.csdn.net/oracle8090/article/details/129205943

来自尚硅谷

一、HashMap

1. HashMap中元素的特点

> HashMap中的所有的key彼此之间是不可重复的、无序的。所有的key就构成一个Set集合。--->key所在的类要重写hashCode()和equals()

> HashMap中的所有的value彼此之间是可重复的、无序的。所有的value就构成一个Collection集合。--->value所在的类要重写equals()

> HashMap中的一个key-value,就构成了一个entry。

> HashMap中的所有的entry彼此之间是不可重复的、无序的。所有的entry就构成了一个Set集合。

2. HashMap源码解析

2.1 jdk7中创建对象和添加数据过程(以JDK1.7.0_07为例说明):

//创建对象的过程中,底层会初始化数组Entry[] table = new Entry[16];

HashMap<String,Integer> map = new HashMap<>();

...

map.put("AA",78); //"AA"和78封装到一个Entry对象中,考虑将此对象添加到table数组中。

...

添加/修改的过程:

将(key1,value1)添加到当前的map中:

首先,需要调用key1所在类的hashCode()方法,计算key1对应的哈希值1,此哈希值1经过某种算法(hash())之后,得到哈希值2。

哈希值2再经过某种算法(indexFor())之后,就确定了(key1,value1)在数组table中的索引位置i。

1.1 如果此索引位置i的数组上没有元素,则(key1,value1)添加成功。 ---->情况1

1.2 如果此索引位置i的数组上有元素(key2,value2),则需要继续比较key1和key2的哈希值2 --->哈希冲突

2.1 如果key1的哈希值2与key2的哈希值2不相同,则(key1,value1)添加成功。 ---->情况2

2.2 如果key1的哈希值2与key2的哈希值2相同,则需要继续比较key1和key2的equals()。要调用key1所在类的equals(),将key2作为参数传递进去。

3.1 调用equals(),返回false: 则(key1,value1)添加成功。 ---->情况3

3.2 调用equals(),返回true: 则认为key1和key2是相同的。默认情况下,value1替换原有的value2。

说明:情况1:将(key1,value1)存放到数组的索引i的位置

情况2,情况3:(key1,value1)元素与现有的(key2,value2)构成单向链表结构,(key1,value1)指向(key2,value2)

随着不断的添加元素,在满足如下的条件的情况下,会考虑扩容:

(size >= threshold) && (null != table[i])

当元素的个数达到临界值(-> 数组的长度 * 加载因子)时,就考虑扩容。默认的临界值 = 16 * 0.75 --> 12.

默认扩容为原来的2倍。

2.2 jdk8与jdk7的不同之处(以jdk1.8.0_271为例):

① 在jdk8中,当我们创建了HashMap实例以后,底层并没有初始化table数组。当首次添加(key,value)时,进行判断,

如果发现table尚未初始化,则对数组进行初始化。

② 在jdk8中,HashMap底层定义了Node内部类,替换jdk7中的Entry内部类。意味着,我们创建的数组是Node[]

③ 在jdk8中,如果当前的(key,value)经过一系列判断之后,可以添加到当前的数组角标i中。如果此时角标i位置上有

元素。在jdk7中是将新的(key,value)指向已有的旧的元素(头插法),而在jdk8中是旧的元素指向新的

(key,value)元素(尾插法)。 "七上八下"

④ jdk7:数组+单向链表

jk8:数组+单向链表 + 红黑树

什么时候会使用单向链表变为红黑树:如果数组索引i位置上的元素的个数达到8,并且数组的长度达到64时,我们就将此索引i位置上

的多个元素改为使用红黑树的结构进行存储。(为什么修改呢?红黑树进行put()/get()/remove()

操作的时间复杂度为O(logn),比单向链表的时间复杂度O(n)的好。性能更高。

什么时候会使用红黑树变为单向链表:当使用红黑树的索引i位置上的元素的个数低于6的时候,就会将红黑树结构退化为单向链表。

2.3 属性/字段:

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 默认的初始容量 16

static final int MAXIMUM_CAPACITY = 1 << 30; //最大容量 1 << 30

static final float DEFAULT_LOAD_FACTOR = 0.75f; //默认加载因子

static final int TREEIFY_THRESHOLD = 8; //默认树化阈值8,当链表的长度达到这个值后,要考虑树化

static final int UNTREEIFY_THRESHOLD = 6;//默认反树化阈值6,当树中结点的个数达到此阈值后,要考虑变为链表

//当单个的链表的结点个数达到8,并且table的长度达到64,才会树化。

//当单个的链表的结点个数达到8,但是table的长度未达到64,会先扩容

static final int MIN_TREEIFY_CAPACITY = 64; //最小树化容量64

transient Node<K,V>[] table; //数组

transient int size; //记录有效映射关系的对数,也是Entry对象的个数

int threshold; //阈值,当size达到阈值时,考虑扩容

final float loadFactor; //加载因子,影响扩容的频率

二、LinkedHashMap

1. LinkedHashMap 与 HashMap 的关系:

> LinkedHashMap 是 HashMap的子类。

> LinkedHashMap在HashMap使用的数组+单向链表+红黑树的基础上,又增加了一对双向链表,记录添加的(key,value)的

先后顺序。便于我们遍历所有的key-value。

LinkedHashMap重写了HashMap的如下方法:

Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {

LinkedHashMap.Entry<K,V> p = new LinkedHashMap.Entry<K,V>(hash, key, value, e);

linkNodeLast(p);

return p;

}

2. 底层结构:LinkedHashMap内部定义了一个Entry

static class Entry<K,V> extends HashMap.Node<K,V> {

Entry<K,V> before, after; //增加的一对双向链表

Entry(int hash, K key, V value, Node<K,V> next) {

super(hash, key, value, next);

}

}

三、HashSet和LinkedHashSet的源码分析

> HashSet底层使用的是HashMap

> LinkedHashSet底层使用的是LinkedHashMap

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

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

相关文章

代码随想录【Day23】| 669. 修剪二叉搜索树、108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树

669. 修剪二叉搜索树 题目链接 题目描述&#xff1a; 给定一个二叉搜索树&#xff0c;同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[L, R]中 (R>L) 。你可能需要改变树的根节点&#xff0c;所以结果应当返回修剪好的二叉搜索树的新…

Git ---- GitHub 操作

Git ---- GitHub 操作1. 创建远程仓库2. 远程仓库操作1. 创建爱你远程仓库别名2. 推送本地分支到远程仓库3. 克隆远程仓库到本地4. 邀请加入团队5. 拉取远程库内容3. 跨团队协作4. SSH 免密登录GitHub 网址&#xff1a;https://github.com/ Ps&#xff1a;全球最大同性交友网站…

makdown模版参考

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

RK系列(RK3568) i2s 音频输入 麦克风驱动

平台&#xff1a;Android12SOC&#xff1a;RK3568外围芯片&#xff1a;XS9922i2s简介&#xff1a;从上图看I2s主要的线有&#xff1a;SDO SCLK LRCK MCLK I2S协议只定义三根信号线&#xff1a;串行时钟信号SCLK(BCLK)、数据信号SD和左右声道选择信号WS。&#xff08;1&#xff…

Leetcode力扣秋招刷题路-0103

从0开始的秋招刷题路&#xff0c;记录下所刷每道题的题解&#xff0c;帮助自己回顾总结 103. 二叉树的锯齿形层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此…

注意力机制详解系列(一):注意力机制概述

&#x1f468;‍&#x1f4bb;作者简介&#xff1a; 大数据专业硕士在读&#xff0c;CSDN人工智能领域博客专家&#xff0c;阿里云专家博主&#xff0c;专注大数据与人工智能知识分享。 &#x1f389;专栏推荐&#xff1a; 目前在写CV方向专栏&#xff0c;更新不限于目标检测、…

SSM+HTML搭建(小白教学)

最近做项目,觉得还是有意义记录以下前后端框架是怎么搭建的,今天给大家介绍介绍SSM:SpringBootSpringMVCMyBatis后端搭建:SpringBoot快速搭建的网站(Spring Initializr)选择创建之后,会下载到一个zip压缩包,对压缩包进行解压(包地址一般选择后端项目的放的文件夹中)用idea打开项…

上岸16K,薪资翻倍,在华为外包做测试是一种什么样的体验····

现在回过头看当初的决定&#xff0c;还是正确的&#xff0c;自己转行成功&#xff0c;现在进入了华为外包测试岗&#xff0c;脱离了工厂生活&#xff0c;薪资也翻了一倍不止。 我17年毕业于一个普通二本学校&#xff0c;电子信息工程学院&#xff0c;是一个很不出名的小本科。…

字符串匹配--strstr函数的模拟实现思路和代码

一&#xff0c;strstr函数 原型&#xff1a; const char * strstr ( const char * str1, const char * str2 );char * strstr ( char * str1, const char * str2 ); strstr是一个字符串匹配函数&#xff0c;在str1中去寻找str2&#xff0c;如果找到&#xff0c;返回str2在…

Tapdata Connector 实用指南:实时数仓场景之数据实时同步至 ClickHouse

【前言】作为中国的 “Fivetran/Airbyte”, Tapdata 是一个以低延迟数据移动为核心优势构建的现代数据平台&#xff0c;内置 60 数据连接器&#xff0c;拥有稳定的实时采集和传输能力、秒级响应的数据实时计算能力、稳定易用的数据实时服务能力&#xff0c;以及低代码可视化操作…

Tina_Linux_系统软件 开发指南

Tina_Linux_系统软件 开发指南 1 概述 编写目的&#xff1a;本文档作为Allwinner Tina Linux系统平台开发指南&#xff0c;旨在帮助软件开发工程师、技术支持工程师快速上手&#xff0c;熟悉Tina Linux系统的开发及调试流程。 适用范围&#xff1a;Tina Linux v3.5及以上版本…

博客管理系统--项目说明

项目体验地址&#xff08;账号&#xff1a;123&#xff0c;密码&#xff1a;123&#xff09;http://120.53.20.213:8080/blog_system/login.html项目码云Gitee地址&#xff1a;https://gitee.com/GoodManSS/project/tree/master/blog_system&#xff08;一&#xff09;准备工作…

常见前端基础面试题(HTML,CSS,JS)(三)

JS 中如何进行数据类型的转换&#xff1f; 类型转换可以分为两种&#xff0c;隐性转换和显性转换 显性转换 主要分为三大类&#xff1a;数值类型、字符串类型、布尔类型 三大类的原始类型值的转换规则我就不一一列举了 数值类型&#xff08;引用类型转换&#xff09; Numbe…

什么是SSL端口?HTTPS配置技术指南

安全套接字层&#xff08;SSL&#xff09;是负责互联网连接的数据身份验证和加密的技术。它加密在两个系统之间&#xff08;通常在服务器和客户端之间&#xff09;之间通过互联网发送的数据&#xff0c;使其保持私密。随着在线隐私的重要性日益增加&#xff0c;您应该熟悉SSL端…

「RISC-V Arch」SBI 规范解读(上)

术语 SBI&#xff0c;Supervisor Binary Interface&#xff0c;管理二进制接口 U-Mode&#xff0c;User mode&#xff0c;用户模式 S-Mode&#xff0c;Supervisor mode&#xff0c;监督模式 VS-Mode&#xff0c;Virtualization Supervisor mode&#xff0c;虚拟机监督模式 …

电商共享购模式,消费增值返利,app开发

在当今以市场需求为主导的数字经济时代&#xff0c;消费者需求呈现出精细化管理和多元化的特性&#xff0c;目标市场日渐完善&#xff0c;另外在大数据技术迅速进步和运用的驱动下&#xff0c;总体行业的发展节奏感也在不断加速。因而&#xff0c;企业需要建立一套灵活多变的经…

HyperGBM用Adversarial Validation解决数据漂移问题

本文作者&#xff1a;杨健&#xff0c;九章云极 DataCanvas 主任架构师 数据漂移问题近年在机器学习领域来越来越得到关注&#xff0c;成为机器学习模型在实际投产中面对的一个主要挑战。当数据的分布随着时间推移逐渐发生变化&#xff0c;需要预测的数据和用于训练的数据分布…

格雷码的实现

格雷码&#xff1a;任意两个相邻的二进制数之间只有一位不同 想必通信专业的学生应该都接触过格雷码&#xff0c;它出现在数电、通信原理等课程里。 如下图所示一个四位格雷码是什么样子的&#xff1a; 格雷码的特点&#xff1a; 其最大的特点是任意上下相邻的两个码值间&am…

线性数据结构:数组 Array

一、前言数组是数据结构还是数据类型&#xff1f;数组只是个名称&#xff0c;它可以描述一组操作&#xff0c;也可以命名这组操作。数组的数据操作&#xff0c;是通过 idx->val 的方式来处理。它不是具体要求内存上要存储着连续的数据才叫数组&#xff0c;而是说&#xff0c…

内网渗透(五十六)之域控安全和跨域攻击-非约束委派攻击

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…