【容器源码篇】Map容器(HashTable,HashMap,TreeMap的特点)

文章目录

  • ⭐容器继承关系
    • 🌹Map容器
      • 🗒️HashTable源码解析
        • 构造方法
        • put方法
        • remove方法
        • rehash扩容
      • 🗒️HashMap源码解析
        • 构造函数
        • get方法
        • put方法
          • 详解
        • 扩容方法
          • 详解
        • 🗒️TreeMap源码解析

在这里插入图片描述

⭐容器继承关系

在这里插入图片描述

🌹Map容器

键值对映射:Map容器中的元素是以键值对的形式存储的,每个键对应一个值。通过键可以快速查找对应的值。

键不重复:Map中的键是唯一的,每个键对应一个值。如果添加已经存在的键,则会更新对应的值。

常用操作:Map提供了添加键值对、获取值、判断是否包含某个键等基本操作。

遍历:可以通过键集、值集或者键值对集合来遍历Map中的元素。

🗒️HashTable源码解析

线程安全:Hashtable 是同步的,可以在多线程环境中安全地使用。这意味着多个线程可以同时读写 Hashtable 而不会出现并发问题。

不允许 null 键或值:Hashtable 不允许键或值为 null,如果尝试插入 null 键或值,会抛出 NullPointerException 异常。

初始容量和加载因子:Hashtable 有一个初始容量和加载因子,当哈希表中的元素数量超过加载因子乘以容量时,哈希表会自动扩容。

构造方法

在这里插入图片描述
默认容量是11,加载因子是0.75
在这里插入图片描述
指定装载容量,加载因子是0.75
在这里插入图片描述
如果用户传入的initialCapacity为0,将初始容量设为1,确保哈希表至少有一个桶用于存储元素。
计算哈希表的扩容阈值,其值为initialCapacity乘以loadFactor的结果与MAX_ARRAY_SIZE + 1之间的较小值。当哈希表中的元素数量超过这个阈值时,会触发扩容操作以保证哈希表的性能。
在这里插入图片描述

在函数内部,首先根据传入的map的大小计算出一个初始容量,并将其和11中的较大值作为Hashtable的容量,并设置加载因子为0.75。然后调用putAll方法将传入的map中的所有键值对复制到新创建的Hashtable中。

put方法

在这里插入图片描述

将指定的键(key)映射到指定的值(value),并将其添加到哈希表中。如果该键已经存在于哈希表中,则用新值替换旧值,并返回旧值。如果该键不存在,则将新键值对添加到哈希表中。该方法是同步的,可以避免多线程环境下的并发问题。需要注意的是,键和值都不能为null。
在这里插入图片描述

hash 是传入键对象(Key)的hashCode值。
0x7FFFFFFF 是一个32位的整数,其二进制表示为一串1,与操作符 “&” 用来获取 hash 的正向32位整数值,确保结果非负。
% tab.length 是对得到的无符号32位整数取模运算,目的是将哈希码映射到哈希表的实际索引位置上,这样即使哈希表大小不同也能保证键均匀分布。
整体来说,这段代码的作用是根据给定的键对象的hashCode值确定其在哈希表数组中的索引位置。

remove方法

在这里插入图片描述

rehash扩容

在这里插入图片描述
获取旧哈希表的容量和映射数组。
计算新哈希表的容量,当新容量超过最大数组大小时,将其设置为最大数组大小。
创建新哈希表映射数组。
更新哈希表的修改次数和阈值。
将旧哈希表中的每个键值对重新哈希到新哈希表中。

🗒️HashMap源码解析

非线程安全:HashMap 不是同步的,因此不适合在多线程环境中直接使用。如果需要在多线程环境中使用,可以通过 Collections.synchronizedMap 方法来创建一个线程安全的 Map。

允许 null 键和值:在 Java 8 之后,HashMap 允许 null 作为键和值。

初始容量和负载因子:HashMap 有一个初始容量和负载因子。当哈希表中的元素数量超过负载因子乘以容量时,哈希表会自动扩容。

构造函数

在这里插入图片描述
这一段代码和上面HashTable的构造函数很像

get方法

在这里插入图片描述
首先根据哈希值和表的长度计算出节点在表中的索引位置,然后获取该位置上的节点。如果该节点存在并且与 给定的键 相等,则返回该节点。如果该节点存在但是是一个TreeNode(红黑树节点),则将获取节点的操作委托给TreeNode的getTreeNode方法。如果该节点存在但是下一个节点不为空,则遍历下一个节点,重复上述判断操作,直到找到相等的节点或者遍历结束。如果在整个表中找不到相等的节点,则返回null。

put方法

在这里插入图片描述
在这里插入图片描述

详解

在这里插入图片描述
Node<K,V>[] tab中tab表示的就是数组。Node<K,V> p中p表示的就是当前插入的节点
在这里插入图片描述
如果数组是空的,那么就通过resize方法来创建一个新的数组
在这里插入图片描述
i表示在数组中插入的位置,计算的方式为(n - 1) & hash。在这里需要判断插入的位置是否是冲突的,如果不冲突就直接newNode,插入到数组中即可

如果冲突了,进入下面的分析

在这里插入图片描述

判断table[i]中的元素是否与插入的key一样,若相同那就直接使用插入的值p替换掉旧的值e。
在这里插入图片描述
判断插入的数据结构是红黑树还是链表,在这里表示如果是红黑树,那就直接putTreeVal到红黑树中

如果是链表,就进入下面的分析
在这里插入图片描述

如果数据结构是链表,首先要遍历table数组是否存在,如果不存在直接newNode(hash, key, value, null)。如果存在了直接使用新的value替换掉旧的。

注意一点:不存在并且在链表末尾插入元素的时候,会判断binCount >= TREEIFY_THRESHOLD - 1。也就是判断当前链表的长度是否大于阈值8,如果大于那就会把当前链表转变成红黑树,方法是treeifyBin
在这里插入图片描述
插入成功之后,还要判断一下实际存在的键值对数量size是否大于阈值threshold。如果大于那就开始扩容了。

扩容方法

在这里插入图片描述

详解

在这里插入图片描述
首先如果超过了数组的最大容量,那么就直接将阈值设置为整数最大值,然后如果没有超过,那就扩容为原来的2倍,这里要注意是oldThr << 1,移位操作来实现的。
在这里插入图片描述

第一个else if表示如果阈值已经初始化过了,那就直接使用旧的阈值。然后第二个else表示如果没有初始化,那就初始化一个新的数组容量和新的阈值。

🗒️TreeMap源码解析

有序性:TreeMap中的键值对根据键的自然顺序或自定义排序规则进行排序,因此可以按照键的顺序进行遍历。

红黑树:TreeMap内部使用红黑树作为数据结构,这种自平衡二叉搜索树能够保持键值对的有序性,并且提供了较快的插入、删除和查找操作。

键的唯一性:TreeMap中的键是唯一的,如果尝试插入一个已存在的键,则会覆盖原有的值。

性能:TreeMap提供了对数时间复杂度的插入、删除和查找操作,适合于需要有序存储和查找的场景。

导航方法:TreeMap提供了许多导航方法,如firstKey()、lastKey()、lowerKey(K key)、higherKey(K key)等,可以方便地进行范围查找和导航操作。

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

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

相关文章

如何在 Mac 上打开、编辑、复制、移动或删除存储在 Windows NTFS 格式 USB 驱动器上的文件 Tuxera NTFS for Mac使用教程

当您获得一台新 Mac 时&#xff0c;它只能读取 Windows NTFS 格式的 USB 驱动器。要将文件添加、保存或写入您的 Mac&#xff0c;您需要一个附加的 NTFS 驱动程序。Tuxera 他可以帮忙实现这一功能&#xff01; Tuxera可以轻松转换驱动器&#xff1a;无论使用Windows PC还是Mac&…

OpenGL的MVP矩阵理解

OpenGL的MVP矩阵理解 右手坐标系 右手坐标系与左手坐标系都是三维笛卡尔坐标系&#xff0c;他们唯一的不同在于z轴的方向&#xff0c;如下图&#xff0c;左边是左手坐标系&#xff0c;右边是右手坐标系 OpenGL中一般用的是右手坐标系 1.模型坐标系&#xff08;Local Space&…

42 ajax 下载文件未配置 responseType blob 导致的文件异常

前言 这是一个最近的关于文件下载碰到的一个问题 主要的情况是, 基于 xhr 发送请求, 获取下载的文件 然后 之后 xhr 这边拿到 字节序列之后, 封装 blob 来进行下载 然后 最开始我们这边没有配置 responseType 为 blob, arraybuffer, 然后 导致下载出来的 文件大小超过了…

Image-Adaptive YOLO for Object Detection in Adverse Weather Conditions(IA-YOLO)

1、总体概述 基于深度学习的目标检测在常规条件的数据集可以获得不错的结果&#xff0c;但是在环境、场景、天气、照度、雾霾等自然条件的综合干扰下&#xff0c;深度学习模型的适应程度变低&#xff0c;检测结果也随之下降&#xff0c;因此研究在复杂气象条件下的目标检测方法…

警务数据仓库的实现

目录 一、SQL Server 2008 R2&#xff08;一&#xff09;SQL Server 的服务功能&#xff08;二&#xff09;SQL Server Management Studio&#xff08;三&#xff09;Microsoft Visual Studio 二、创建集成服务项目三、配置“旅馆_ETL”数据流任务四、配置“人员_ETL”数据流任…

k8s安装traefik作为ingress

一、先来介绍下Ingress Ingress 这个东西是 1.2 后才出现的&#xff0c;通过 Ingress 用户可以实现使用 nginx 等开源的反向代理负载均衡器实现对外暴露服务&#xff0c;以下详细说一下 Ingress&#xff0c;毕竟 traefik 用的就是 Ingress 使用 Ingress 时一般会有三个组件: …

基于SSM的高校普法系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的高校普法系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spri…

inkscape中文版本 G代码生成器(支持中英文及数字)使用

inkscape G代码生成器&#xff08;支持中英文及数字&#xff09;使用 1 inkscape安装1. 界面介绍2. 基本操作3. 图形编辑4. 图层管理5. 文件操作6. 高级功能7. 学习资源 2 laserengraver插件安装3 inkscape 使用candle 验证G代码效果 1 inkscape安装 跟着提示默认按键即可。 软…

HTML网站的概念

目录 前言&#xff1a; 1.什么是网页&#xff1a; 2.什么是网站&#xff1a; 示例&#xff1a; 3.服务器&#xff1a; 总结&#xff1a; 前言&#xff1a; HTML也称Hyper Text Markup Language&#xff0c;意思是超文本标记语言&#xff0c;同时HTML也是前端的基础&…

Linux 环境安装Nginx—源码和Dokcer两种安装方式

一、源代码编译安装Nginx 1.下载最新nginx源码 以nginx-1.25.3.tar.gz为例&#xff1a; 可以使用命令(联网)&#xff1a;curl -O http://nginx.org/download/nginx-1.25.3.tar.gz或在官网下载.tar.gz 2.解压缩 tar -zxvf nginx-1.25.3.tar.gz cd nginx-1.25.3/ 3.安装依赖…

HarmonyOS实战开发-实现自定义弹窗

介绍 本篇Codelab基于ArkTS的声明式开发范式实现了三种不同的弹窗&#xff0c;第一种直接使用公共组件&#xff0c;后两种使用CustomDialogController实现自定义弹窗&#xff0c;效果如图所示 相关概念 AlertDialog&#xff1a;警告弹窗&#xff0c;可设置文本内容和响应回调…

【javaWeb 第八篇】后端-Mybatis(万字详细学习)

Mybatis框架 前言MybatisMybatis入门配置SQL提示JDBC数据库连接池lombok Mybatis基础操作日志输出Mybatis的动态SQL 前言 这篇是作者学习数据持久层框架Mybatis的学习笔记&#xff0c;希望对大家有所帮助&#xff0c;希望大家能够与作者交流讨论 Mybatis Mybatis是一款优秀的…

Android 开发 Spinner setSelection 不起作用

问题 Android 开发 Spinner setSelection 不起作用 详细问题 笔者进行Android项目开发&#xff0c;根据上一个页面用户选择数据&#xff0c;显示当前页面Spinner选项&#xff0c;调用 Spinner setSelection 不起作用。 相关java代码 spinner.setAdapter(adapter); …

uniapp对接萤石云 实现监控播放、云台控制、截图、录像、历史映像等功能

萤石云开发平台地址&#xff1a;文档概述 萤石开放平台API文档 (ys7.com) 萤石云监控播放 首先引入萤石云js js地址&#xff1a;GitHub - Ezviz-OpenBiz/EZUIKit-JavaScript-npm: 轻应用npm版本&#xff0c;降低接入难度&#xff0c;适配自定义UI&#xff0c;适配主流框架 vi…

C语言例4-35:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。百钱买百鸡、问鸡翁、鸡母和鸡雏各几何?

方法一&#xff1a; 代码如下&#xff1a; //鸡翁一&#xff0c;值钱五&#xff1b;鸡母一&#xff0c;值钱三&#xff1b;鸡雏三&#xff0c;值钱一。百钱买百鸡、问鸡翁、鸡母和鸡雏各几何&#xff1f; //方法一&#xff1a; #include<stdio.h> int main(void) {int x…

简易挛生分拣系统设计

1 工效组合展示 2 方案规划设计 3 数字挛生建模 基础建模、动画设计、模型导出 4 软件体系架构 5 Web交互设计 5.1 页面架构 5.2 初始构造 5.3 模型运用 5.4 WS通信 5.5 运行展现 6 服务支撑编码 6.1 整体调度 6.2 WS服务 6.3 C/S通信 7 系统级调试完善

李雅普诺夫函数

李雅普诺夫函数是一种用于描述动力系统稳定性的数学工具。它在动力系统和控制理论中具有广泛的应用&#xff0c;尤其是在研究非线性系统的稳定性方面。 李雅普诺夫函数通常用于证明动力系统在一些条件下是稳定的。一个李雅普诺夫函数是一个实数值函数&#xff0c;通常表示为 V…

使用mybatis的@Interceptor实现拦截sql

一 mybatis的拦截器 1.1 拦截器介绍 拦截器是一种基于 AOP&#xff08;面向切面编程&#xff09;的技术&#xff0c;它可以在目标对象的方法执行前后插入自定义的逻辑。 1.2 语法介绍 1.注解Intercepts Intercepts({Signature(type StatementHandler.class, method “…

【Java - 框架 - Lombok】(2) SpringBoot整合Lombok完成日志的创建使用 - 快速上手;

"SpringBoot"整合"Lombok"完成日志的创建使用 - 快速上手&#xff1b; 环境 “Java"版本"1.8.0_202”&#xff1b;“Lombok"版本"1.18.20”&#xff1b;“Spring Boot"版本"2.5.9”&#xff1b;“Windows 11 专业版_22621…

华硕ROG幻X笔记本GZ301VV原厂OEM预装Win11系统安装包下载

ASUS华硕幻X电脑原装出厂Windows11系统&#xff0c;恢复出厂开箱状态系统 链接&#xff1a;https://pan.baidu.com/s/1RkPr5IscTUolYJVUrxTyhQ?pwdhob2 提取码&#xff1a;hob2 适用型号&#xff1a;GZ301VV、GZ301VU、GZ301VF 原装出厂系统自带所有驱动、出厂主题壁纸、系统…