Map接口-实现类HashMap

目录

一、什么是Map?

二、实现类HashMap

1.关键特点

无序、key唯一、value允许重复、key和value允许为null。

2.数据结构

2.1 JDK 1.7

2.2 JDK 1.8

2.3 关键参数

2.4 关键计算

3.扩容方式

3.1 初始化

3.2 扩容

4.常见方法

4.1 根据key存入value

4.2 根据key获取value

4.3 判断Map

4.4 根据key替换value

4.5 根据key删除value

4.6 遍历Map

5.HashMap(put)底层原理


一、什么是Map?

(1)Map是一种键值对集合,每一个元素都包含一个 键对象(key) 和一个 值对象(value)。

(2)Map集合中,键不允许重复,值可以重复。 (比如身份证与姓名)

(3)键和值是一一对应的,通过键可以找到与之对应的唯一的值。

(4)key和value必须是引用数据类型。

二、实现类HashMap

1.关键特点

无序、key唯一、value允许重复、key和value允许为null。

2.数据结构

2.1 JDK 1.7

数组+单向链表

在链表中插入元素,采用【头插法】

2.2 JDK 1.8

数组+单向链表+红黑树

在链表中插入元素时,采用【尾插法】

2.3 关键参数

(1)Node<K, V>[ ] table:

                保存KV键值对的数组,每个KV键值对都被封装成一个Node对象。

                数组容量决定了HashMap对内存的占用大小。

(2)float loadFactor:

                加载因子(填充因子)。

                加载因子默认为0.75,代表HashMap对数组容量的使用率为75%,超过该使用率,则数组需要进行扩容。

                加载因子决定了HashMap对数组的使用率,加载因子越高,则表示允许填满的元素就越多,集合的空间利用率就越高,但是冲突的机会增加。反之,越小则冲突的机会就会越少,但是空间很多就浪费。

(3)int threshold:

                扩容阈值。

                用于判断数组是否需要进行扩容。

                扩容阈值threshold = 数组容量 × 加载因子。

(4)size : int 

                KV键值对的数量。

2.4 关键计算

(1)hash()函数:

(h = key.hashCode()) ^ (h >>> 16):在key原有哈希值的基础上,与哈希值的高16位进行异或运算,计算出的哈希值更佳散列,不易出现哈希冲突。

(2)下标计算:JDK 1.7 :hash % 数组长度。

                            JDK 1.8:(数组长度 - 1) & hash。提高性能--数组长度必须为2的N次幂。

3.扩容方式

3.1 初始化

(1)public HashMap():加载因子默认为为0.75。

(2)public HashMap(int initialCapacity, float loadFactor):指定容量和加载因子。

3.2 扩容

(1)添加第一个KV键值对,数组如果为空,则默认扩容为16。

(2)加入元素时,如果链表长度大于阈值(默认为 8)并且数组长度小于64,会产生数组扩容;*2。

(3)添加元素后,当HashMap中的元素个数超过【数组大小 × 加载因子(LoadFactor)】时,原数组扩容2倍。例如:加载因子(LoadFactor)的默认值为0.75,数组容量默认为16,当HashMap中元素个数超过16 × 0.75=12的时候,数组的容量扩容为16×2 =32;

4.常见方法

4.1 根据key存入value

(1)V put(K key, V value):存入【KV键值对】,如果key存在,则覆盖【原value值】,保存后,返回【原value值】。

(2)void putAll(Map m):将【指定map】中的所有KV键值对,存入【当前map】。

(3)V putIfAbsent(K key, V value):如果key不存在,则保存value,并返回【null】;如果key已经存在,则不保存value,并返回【原value值】。

4.2 根据key获取value

(1)V get(Object key):根据key,返回【value值】;如果key不存在,则返回【null】。

(2)V getOrDefault(Object key, V defaultValue):根据key,返回【value值】;如果key不存在,则返回【默认值】。

4.3 判断Map

(1)boolean containsKey(Object key):判断key是否存在。

(2)boolean containsValue(Object value):判断value是否存在。

(3)boolean isEmpty():判断map中的【KV键值对】数量是否为0。

(4)int size():获取map中的【KV键值对】数量。

4.4 根据key替换value

(1)V replace(K key, V value):根据key,替换value,并返回【原value值】;如果key不存在,则返回【null】。

(2)boolean replace(K key, V oldValue, V newValue):根据key和value,替换value,修改成功,返回【true】;如果key和value不存在,则替换失败,返回【false】。

4.5 根据key删除value

(1)V remove(Object key):根据key,删除【KV键值对】,并返回【原value值】。

(2)boolean remove(Object key, Object value):根据key和value,删除【KV键值对】,则删除成功,返回【true】;如果key和value不存在,则删除失败,返回【false】。

(3)clear():清除map中的键值对。

4.6 遍历Map

(1)Set<K> keySet():获取所有key。

(2)Collection<V> values():获取所有value。

(3)Set<Map.Entry<K,V>> entrySet():获取所有【KV键值对】,每个【KV键值对】使用【Entry类型的对象】封装。

public class Demo01 {public static void main(String[] args) {//HashMap 无序,且key是唯一的,value是可重复的HashMap<String,String> hashMap=new HashMap<>();hashMap.put("110","北京");hashMap.put("120","天津");hashMap.put("130","河北");hashMap.put("610","陕西");hashMap.put("610","甘肃");hashMap.put("620","甘肃");System.out.println(hashMap);}
}
public class Demo02 {public static void main(String[] args) {HashMap<String, String> hashMap = new HashMap<>();insertElement(hashMap);//selectElement(hashMap);deleteElement(hashMap);}public static void insertElement(HashMap<String, String> hashMap) {System.out.println("========进入到添加方法中========");//1.V put(K key, V value)存键值对,如果集合不存在此键,直接存,返回值为null//当存在此键时,返回值为上一次的键对应的value,用此value覆盖String item1 = hashMap.put("110", "北京");String item2 = hashMap.put("110", "天津");hashMap.put("130", "河北");hashMap.put("610", "陕西");System.out.println("第一次存返回值:" + item1);System.out.println("第二次存返回值:" + item2);//void putAll(Map m)HashMap<String, String> hashMap1 = new HashMap<>();hashMap1.put("620", "甘肃");hashMap1.put("630", "宁夏");hashMap1.put("610", "内蒙");//将指定map中的所有KV键值对,存入到当前map;hashMap.putAll(hashMap1);System.out.println(hashMap);//V  putIfAbsent(K key,V value)如果存在此键,返回值为键对应的旧值,如果不存在则存返回nullString oldValue = hashMap.putIfAbsent("611", "西安");System.out.println("putIfAbsent再次存610的键:" + oldValue);System.out.println(hashMap);}public static void selectElement(HashMap<String, String> hashMap) {System.out.println("=======进入到查看方法中=======");System.out.println("目前map中的元素为:" + hashMap);//V get(Object key)根据key,返回value值,如果key不存在,则返回nullString value1 = hashMap.get("120");System.out.println("键120对应的值为" + value1);//V getOrDefault(Object key,V defaultValue)//根据key,返回value值,如果key不存咋,则返回默认值String value2 = hashMap.getOrDefault("120", "不知道");System.out.println("键120对应的值为:" + value2);//boolean containsKey(Object key)判断key是否存在boolean b1 = hashMap.containsKey("611");System.out.println("键611是否存在:" + b1);//boolean containsValue(Object value)判断value是否存在boolean b2 = hashMap.containsValue("宁夏");System.out.println("值宁夏是否存在:" + b2);//boolean isEmpty()判断map中的【KV键值对】数量是否为0System.out.println("集合map是否为空:" + hashMap.isEmpty());//int size()获取map中的【KV键值对】数量System.out.println("集合的size:" + hashMap.size());}public static void deleteElement(HashMap<String, String> hashMap){System.out.println("========进入到删除和修改方法中========");System.out.println("目前map中的元素为:" + hashMap);//V replace(K key, V value)根据key,替换value,并返回【原value值】;如果key不存在,则返回【null】String value=hashMap.replace("110","北京");System.out.println(value);System.out.println("修改后的hashmap:"+hashMap);//boolean replace(K key, V oldValue, V newValue)//根据key和value,替换value,修改成功,返回【true】;如果key和value不存在,则替换失败,返回【false】;boolean b1=hashMap.replace("610","内蒙","陕西");System.out.println(b1);System.out.println("修改后的hashmap:"+hashMap);//V remove(Object key)根据key,删除【KV键值对】,并返回【原value值】String str=hashMap.remove("130");System.out.println(str);System.out.println("删除后的hashmap:"+hashMap);//boolean remove(Object key, Object value)//根据key和value,删除【KV键值对】,则删除成功,返回【true】;如果key和value不存在,则删除失败,返回【false】;boolean b2=hashMap.remove("630","陕西");System.out.println(b2);System.out.println("删除后的hashmap:"+hashMap);//clear()hashMap.clear();System.out.println("清空后:"+hashMap);}
}
public class Demo03 {public static void main(String[] args) {HashMap<String,String> hashMap=new HashMap<>();hashMap.put("110","北京");hashMap.put("120","天津");hashMap.put("130","河北");hashMap.put("610","陕西");hashMap.put("620","甘肃");System.out.println(hashMap);//1.Set<K> keySet()获取所有的键Set<String> keys = hashMap.keySet();for (String key : keys) {String value = hashMap.get(key);System.out.printf("键为:%s - 值为%s\n", key, value);}//2.获取所有的value Collection<V> values()Collection<String> values = hashMap.values();System.out.println(values);//3.获取所有的键值对集合对象Set<Map.Entry<String, String>> entries = hashMap.entrySet();for (Map.Entry<String, String> entry : entries) {System.out.println(entry.getKey() + "==" + entry.getValue());}}
}

5.HashMap(put)底层原理

/*** 数据结构: Node<K,V>[] table, 数组 + 链表 + 红黑树* put整理:* 1.通过i = (n - 1) & hash计算当前键值对要存放的下标位置, 此处元素是否为null,如果为null直接存储* 2.如果不为null,判断当前的下标元素key是否和要存储的key完全一样, key一样, 则value进行覆盖* 3.键如果不同, 则产生了hash冲突, 将当前要存放的键值对存放进来*    3.1判断当前的节点是否是树形节点, 如果是树形节点, 以树形存放方式操作*    3.2如果不是树形节点, 就是链表: 找p.next == null的位置(找的过程中也会和链表的每个元素的key进行相等比较),*        去进行p.next的赋值操作*        链表元素个数的判断>8 && 数组长度 <64  -- 扩容, 2倍扩容*        链表元素个数的判断>8 && 数组长度 >64  会将链表转换为红黑树**        存放完元素如果达到扩容阈值(容量 × 加载因子,默认 0.75), 2倍扩容。* 扩容:* 无参构造初始化对象, 第一次添加元素时, 首次扩容到16

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

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

相关文章

深入解析Hadoop如何实现数据可靠性:三副本策略、校验和验证与Pipeline复制

Hadoop数据可靠性的重要性在大数据时代&#xff0c;数据可靠性已成为企业数字化转型的生命线。根据IDC预测&#xff0c;到2025年全球数据总量将增长至175ZB&#xff0c;其中企业数据占比超过60%。面对如此庞大的数据规模&#xff0c;任何数据丢失或损坏都可能造成数百万美元的经…

15.6 DeepSpeed+Transformers实战:LLaMA-7B训练效率提升210%,显存直降73%

DeepSpeedTransformers实战:LLaMA-7B训练效率提升210%的底层逻辑与实操指南 当LLaMA-7B的训练显存需求达到78GB时,单卡A100(80GB)几乎濒临溢出,更不用说普通GPU集群。而DeepSpeed与Hugging Face Transformers的深度集成,通过"ZeRO三阶段优化+混合精度+梯度检查点&q…

Nginx + PM2 实现Express API + React 前端 本地测试服务器搭建

一、工具准备 openSSL&#xff1a;需要针对https请求头 生成对应的 自签名证书。 Nginx&#xff1a;服务器搭建工具 nodeJS: Express API运行环境 PM2: node进程管理器。用于替代npm命令管理 启动命令。 二、openSSL 本地自签名证书生成。 创建服务器空文件夹&#xff08…

OTG原理讲解

文章目录一、什么是 OTG&#xff08;USB On-The-Go&#xff09;&#xff1f;✅ OTG 的定义&#xff1a;二、传统 USB 与 OTG 的区别三、OTG 的核心机制&#xff1a;**通过 ID 引脚判断角色**1. 对于 Micro-USB OTG&#xff1a;2. 电路如何感知 ID 引脚&#xff1f;四、OTG 电路…

数据结构系列之红黑树

前言 红黑树是比较重要的一颗树了&#xff0c;map和set的底层就是红黑树&#xff0c;一定要牢牢记住。 一、什么是红黑树 首先&#xff1a;红黑树仍然是一颗搜索二叉树&#xff0c;但他引入了颜色这一概念&#xff0c;每个结点多一个存储位来存储颜色&#xff0c;它通过维护下…

在OpenMP中,#pragma omp的使用

在OpenMP中&#xff0c;#pragma omp for 和 #pragma omp parallel for&#xff08;或 #pragma omp parallel num_threads(N)&#xff09;有本质区别&#xff0c;主要体现在 并行区域的创建 和 工作分配方式 上。以下是详细对比&#xff1a;1. #pragma omp for 作用 仅分配循环迭…

停止“玩具式”试探:深入拆解ChatGPT Agent的技术栈与实战避坑指南

摘要&#xff1a; 当许多人还在用ChatGPT写周报、生成样板代码时&#xff0c;其底层的Agent化能力已经预示着一场深刻的开发范式变革。这不再是简单的“AI辅助”&#xff0c;而是“人机协同”的雏形。本文旨在穿透表面的功能宣传&#xff0c;从技术栈层面拆解Agent模式的实现基…

element-plus安装以及使用

element-plus时为vue.js 3开发的组件库。 在引入前需要做如下准备 安装node.js https://blog.csdn.net/zlpzlpzyd/article/details/147704723 安装vue的脚手架vue-cli https://blog.csdn.net/zlpzlpzyd/article/details/149647351 安装element-plus github地址 https://git…

学习随想录-- web3学习入门计划

#60 转方向 web3 golang 以太坊应用 这是课表部分&#xff08;Golang以太坊方向&#xff09; Sheet b站up学习计划 第一阶段&#xff1a;基础能力构建&#xff08;1-2 个月&#xff09; 学习目标 掌握 Golang 核心语法与以太坊底层基础概念&#xff0c;建立开发知识框架。…

【RAG优化】PDF复杂表格解析问题分析

在构建检索增强生成(RAG)应用时,PDF文档无疑是最重要、也最普遍的知识来源之一。然而,PDF中潜藏着RAG系统的难点问题——复杂表格。这些表格富含高密度的结构化信息,对回答精准问题至关重要,但其复杂的视觉布局(多层表头、合并单元格、跨页表格等)常常让标准的文本提取…

ReAct Agent(LangGraph实现)

文章目录参考资料一 AI Agent二 ReAct三 LangGraph实现ReAct代理3.1 SerperAPI实时联网搜索3.2 ReAct实现参考资料 entic RAG 架构的基本原理与应用入门 一 AI Agent AI Agent 整个过程是一个动态循环。Agent不断从环境中学习&#xff0c;通过其行动影响环境&#xff0c;然后…

如何从0到1的建立组织级项目管理体系【现状诊断】

今天我想给大家分享是“如何在企业中从0到1的去建立PMO的组织级项目管理体系。”的系列文章&#xff0c;这是我近几年来一直在努力的尝试去探索和实践的过程&#xff0c;从0到1的过程。当我最开始去接手这样一个场景的时候所需要做的第一件事情是诊断和差距分析。这是多年以来做…

网络通信协议详解:TCP协议 vs HTTP协议

在计算机网络中&#xff0c;TCP&#xff08;传输控制协议&#xff09;和HTTP&#xff08;超文本传输协议&#xff09;是两个核心协议&#xff0c;但它们的职责和层级完全不同。TCP是底层传输协议&#xff0c;负责数据的可靠传输&#xff1b;HTTP是应用层协议&#xff0c;定义了…

[Qt]QString隐式拷贝

引言在Qt框架中&#xff0c;QString 作为字符串处理的核心类&#xff0c;其高效的内存管理机制一直是开发者津津乐道的特性。这背后的关键便是 隐式共享&#xff08;Implicit Sharing&#xff09;&#xff0c;也称为 写时复制&#xff08;Copy-On-Write, COW&#xff09;。本文…

命令行创建 UV 环境及本地化实战演示—— 基于《Python 多版本与开发环境治理架构设计》的最佳实践

命令行创建 UV 环境及本地化实战&#xff1a;基于架构设计的最佳实践 Python 多版本环境治理理念驱动的系统架构设计&#xff1a;三维治理、四级隔离、五项自治 原则-CSDN博客 使用 Conda 工具链创建 UV 本地虚拟环境全记录——基于《Python 多版本与开发环境治理架构设计》-CS…

跨域问题全解:从原理到实战

在计算机网络中&#xff0c;跨域&#xff08;Cross-Origin&#xff09; 指的是浏览器出于安全考虑&#xff0c;限制网页脚本&#xff08;如 JavaScript&#xff09;向与当前页面不同源&#xff08;Origin&#xff09; 的服务器发起请求的行为。这是由浏览器的同源策略&#xff…

(46)elasticsearch-华为云CCE无状态负载部署

一、准备好elasticsearch镜像并提前上传到镜像仓库 此次准备的是elasticsearch:v7.10.2 二、开始部署 负载名称:es-deployment 注意:内部配额太低会造成多次重启 环境变量: #单节点启动(实例pod可以多增加几个) discovery.type single-node 三、添加svc 四、注意:…

HCLP--MGER综合实验

一、拓扑图二、需求1、R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有I地址; 2、R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方&#xff0c; R2与R5之间使用ppp的CHAP认证&#xff0c;R5为主认证方; R3与R5之间使用HDLc封装; 3、R1、R2、R3构建一…

idea中无法删除模块,只能remove?

1.先对module右键想要删除的module&#xff0c;选择remove module&#xff08;这是idea为了避免误操作&#xff09; 2.在remove module后&#xff0c;模块并未从项目结构中删除&#xff08;磁盘中也依旧存在&#xff09;&#xff0c;但再次右击你会发现&#xff0c;出现了del…

青藤天睿RASP再次发威!捕获E签宝RCE 0day漏洞

在2025年HVV关键攻防节点上&#xff0c;攻击队对E签宝电子合同服务发起的0day攻击被青藤天睿RASP截获。该漏洞可使攻击者在未授权情况下实现服务器远程代码执行&#xff08;RCE&#xff09;&#xff0c;进而控制服务器&#xff0c;构成横向渗透的关键跳板。>>>>漏洞…