【java数据结构】HashMap和HashSet
目录
一.认识哈希表:
1.1什么是哈希表?
1.2哈希表的表示:
1.3常见哈希函数:
二.认识HashMap和HashSet:
2.1关于Map.Entry的说明:,>
2.2Map常用方法说明:
2.3HashMap的使用案例:
2.4Set常见方法说明:
2.5HashSet使用案例:
源码:
一.认识哈希表:
1.1什么是哈希表?
之前的学习中,如果我们要查找一个元素,肯定是要经过比较的,那有没有一种办法,可以不用经过比较,直接就能拿到呢?
如果我们能构造一种存储结构,通过一种函数 (hashFunc) 使元素的存储位置与函数得出的关键码之间能够建立一一映射的关系,那么在查找某个元素的时候,就能通过这个函数来很快的找到该元素所在的位置。
这种函数就叫做哈希(散列)函数,上述所说构造出来的结构,叫做哈希表或者称为散列表。
哈希表简介:
哈希表(Hash Table):也叫做散列表。是根据关键码值(Key Value)直接进行访问的数据结构。哈希表通过「键 key 」和「映射函数 Hash(key) 」计算出对应的「值 value」,把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做「哈希函数(散列函数)」,存放记录的数组叫做「哈希表(散列表)」。
1.2哈希表的表示:
举个栗子:为了记录一个班的学生的信息,分别包括学号和姓名。我们就可以用哈希表(数组加链表)来记录,这里学号(关键值key)通过哈希函数得到一个数组下标,这个下标就是这个学生信息存放在对应数组中的位置,同时学生的信息(姓名和学号)叫做键值对,又称作Entry
使用方法:
- 向哈希表中插入一个关键码值:哈希函数决定该关键字的对应值应该存放到表中的哪个区块,并将对应值存放到该区块中。
- 在哈希表中搜索一个关键码值:使用相同的哈希函数从哈希表中查找对应的区块,并在特定的区块搜索该关键字对应的值。
- 实现哈希表: 数组+链表 或者 数组+二叉树
1.3常见哈希函数:
- 直接定值法--(常用):取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B 优点:简单、均匀 缺点:需要事先知道关 键字的分布情况 使用场景:适合查找比较小且连续的情况
- . 除留余数法--(常用) :
设散列表中允许的 地址数为 m ,取一个不大于 m ,但最接近或者等于 m 的质数 p 作为除数,按照哈希函数: Hash(key) = key% p(p<=m), 将关键码转换成哈希地址 例如:![]()
二.认识HashMap和HashSet:
HashMap和HashSet是Java集合框架中的两个常用类,它们都实现了Set接口,但在实现原理和用途上有一些区别。
- HashMap:HashMap是基于哈希表的实现,它使用键值对(key-value)的方式存储数据。HashMap允许存储null键和null值,并且可以存储重复的值,但不允许重复的键。HashMap内部使用哈希函数将键映射到哈希表的索引位置,以实现快速的插入、删除和查找操作。HashMap的查找操作是通过键来进行的,因此可以根据键快速地获取对应的值。
- HashSet:HashSet也是基于哈希表的实现,它存储唯一的元素,不允许重复值。HashSet允许存储null值,但只能存储一个null元素。HashSet内部使用哈希函数将元素映射到哈希表的索引位置,以实现快速的插入、删除和查找操作。HashSet的查找操作是通过元素来进行的,因此可以根据元素快速地判断是否存在于集合中。
2.1关于Map.Entry<K, V>的说明:
方法 | 解释 |
K getKey () | 返回 entry 中的 key |
V getValue () | 返回 entry 中的 value |
V setValue(V value) | 将键值对中的 value 替换为指定 value |
2.2Map常用方法说明:
2.3HashMap的使用案例:
基础操作:
Map<String, String> m = new HashMap<>();// put(key, value):插入key-value的键值对// 如果key不存在,会将key-value的键值对插入到map中,返回nullm.put("林冲", "豹子头");m.put("鲁智深", "花和尚");m.put("武松", "行者");m.put("宋江", "及时雨");String str = m.put("李逵", "黑旋风");m.remove("武松","行者");System.out.println("map的大小(size):" + m.size());System.out.println("map中的元素:" + m);System.out.println("这时str为空: " + str);// put(key,value): 注意key不能为空,但是value可以为空m.put("无名", null); // key如果为空,会抛出空指针异常System.out.println("当前map的大小: " + m.size());str = m.put("李逵", "铁牛");System.out.println("返回旧的value值: " + str);System.out.println("得到Key所对应的value值: " + m.get("李逵"));
运行结果:
GetOrDefault()和containKey(key):
//GetOrDefault(): 如果key存在,返回与key所对应的value,如果key不存在,返回一个默认值System.out.println("=========================================");System.out.println("李逵存在,返回key对应的value: " + m.getOrDefault("李逵", "牛牛"));System.out.println("史进不存在,返回一个默认值: " + m.getOrDefault("史进", "九龙纹"));System.out.println("=========================================");//containKey(key):检测key是否包含在Map中,时间复杂度:O(logN)System.out.println(m.containsValue("豹子头"));System.out.println(m.containsValue("行者"));
运行结果:
三种遍历方法:
System.out.println("-----key ------value -----Entry的遍历方法:----------");System.out.println("key遍历: ");for (String s : m.keySet()) {System.out.print(s + " ");}System.out.println();System.out.println("value遍历: ");for (String s : m.values()) {System.out.print(s + " ");}System.out.println();System.out.println("entry遍历: ");for (Map.Entry<String, String> entry : m.entrySet()) {System.out.println(entry.getKey() + "--->" + entry.getValue());}
运行结果:
注意:
1. Map 是一个接口,不能直接实例化对象 ,如果 要实例化对象只能实例化其实现类 TreeMap 或者 HashMap2. Map 中存放键值对的 Key 是唯一的, value 是可以重复的3. Map 中的 Key 可以全部分离出来,存储到 Set 中 来进行访问 ( 因为 Key 不能重复 ) 。4. Map 中的 value 可以全部分离出来,存储在 Collection 的任何一个子集合中 (value 可能有重复 ) 。5. Map 中键值对的 Key 不能直接修改, value 可以修改,如果要修改 key ,只能先将该 key 删除掉,然后再来进行重新插入。
2.4Set常见方法说明:
方法 | 解释 |
boolean add (E e) | 添加元素,但重复元素不会被添加成功 |
void clear () | 清空集合 |
boolean contains (Object o) | 判断 o 是否在集合中 |
Iterator<E> iterator () | 返回迭代器 |
boolean remove (Object o) | 删除集合中的 o |
int size() | 返回set中元素的个数 |
boolean isEmpty() | 检测 set 是否为空,空返回 true ,否则返回 false |
Object[] toArray() | 将 set 中的元素转换为数组返回 |
boolean containsAll(Collection<?> c) | 集合 c 中的元素是否在 set 中全部存在,是返回 true ,否则返回 false |
boolean addAll(Collection<? extends E> c) | 将集合 c 中的元素添加到 set 中,可以达到去重的效果 |
2.5HashSet使用案例:
System.out.println("================HashSet===============");Set<String> s = new HashSet<>();boolean isIn = s.add("apple");s.add("orange");s.add("peach");s.add("banana");System.out.println(s.size());System.out.println(s);System.out.println("add(key): 如果key不存在,则插入,返回true: " + isIn);isIn = s.add("apple");System.out.println("add(key):如果key存在,则返回false: " + isIn);// contains(key): 如果key存在,返回true,否则返回falseSystem.out.println(s.contains("apple"));System.out.println(s.contains("watermelen"));s.remove("apple");// remove(key): key存在,删除成功返回trueSystem.out.println(s);// key不存在,删除失败返回false , key为空,System.out.println("迭代器遍历:");Iterator<String> it = s.iterator();while (it.hasNext()) {System.out.print(it.next() + " ");}
运行结果:
注意:
1. Set 是继承自Collection的一个接口类2. Set 中只存储了 key ,并且要求 key 一定要唯一3. Set 的底层是使用 Map 来实现的,其使用 key 与 Object 的一个默认对象作为键值对插入到 Map 中的4. 实现 Set 接口的常用类有 TreeSet 和 HashSet ,还有一个 LinkedHashSet , LinkedHashSet 是在 HashSet 的基础上维护了一个双向链表来记录元素的插入次序。5. Set 中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入6. Set 中不能插入null的key
源码:
import java.util.TreeMap;
import java.util.Set;
import java.util.Map;public class Test1 {public static void main(String[] args) {Map<String, String> m = new HashMap<>();// put(key, value):插入key-value的键值对// 如果key不存在,会将key-value的键值对插入到map中,返回nullm.put("林冲", "豹子头");m.put("鲁智深", "花和尚");m.put("武松", "行者");m.put("宋江", "及时雨");String str = m.put("李逵", "黑旋风");m.remove("武松","行者");System.out.println("map的大小(size):" + m.size());System.out.println("map中的元素:" + m);System.out.println("这时str为空: " + str);// put(key,value): 注意key不能为空,但是value可以为空m.put("无名", null); // key如果为空,会抛出空指针异常System.out.println("当前map的大小: " + m.size());str = m.put("李逵", "铁牛");System.out.println("返回旧的value值: " + str);System.out.println("得到Key所对应的value值: " + m.get("李逵"));//GetOrDefault(): 如果key存在,返回与key所对应的value,如果key不存在,返回一个默认值System.out.println("=========================================");System.out.println("李逵存在,返回key对应的value: " + m.getOrDefault("李逵", "牛牛"));System.out.println("史进不存在,返回一个默认值: " + m.getOrDefault("史进", "九龙纹"));System.out.println("=========================================");//containKey(key):检测key是否包含在Map中,时间复杂度:O(logN)System.out.println(m.containsValue("豹子头"));System.out.println(m.containsValue("行者"));System.out.println("-----key ------value -----Entry的遍历方法:----------");System.out.println("key遍历: ");for (String s : m.keySet()) {System.out.print(s + " ");}System.out.println();System.out.println("value遍历: ");for (String s : m.values()) {System.out.print(s + " ");}System.out.println();System.out.println("entry遍历: ");for (Map.Entry<String, String> entry : m.entrySet()) {System.out.println(entry.getKey() + "--->" + entry.getValue());}System.out.println("================HashSet===============");Set<String> s = new HashSet<>();boolean isIn = s.add("apple");s.add("orange");s.add("peach");s.add("banana");System.out.println(s.size());System.out.println(s);System.out.println("add(key): 如果key不存在,则插入,返回true: " + isIn);isIn = s.add("apple");System.out.println("add(key):如果key存在,则返回false: " + isIn);// contains(key): 如果key存在,返回true,否则返回falseSystem.out.println(s.contains("apple"));System.out.println(s.contains("watermelen"));s.remove("apple");// remove(key): key存在,删除成功返回trueSystem.out.println(s);// key不存在,删除失败返回false , key为空,System.out.println("迭代器遍历:");Iterator<String> it = s.iterator();while (it.hasNext()) {System.out.print(it.next() + " ");}}
}
结语: 写博客不仅仅是为了分享学习经历,同时这也有利于我巩固自己的知识点,总结该知识点,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进。同时也希望读者们不吝啬你们的点赞+收藏+关注,你们的鼓励是我创作的最大动力!
相关文章:

【java数据结构】HashMap和HashSet
目录 一.认识哈希表: 1.1什么是哈希表? 1.2哈希表的表示: 1.3常见哈希函数: 二.认识HashMap和HashSet: 2.1关于Map.Entry的说明:,> 2.2Map常用方法说明: 2.3HashMap的使用案例: 2.4Set常见方法…...

基于Springboot的高校汉服租赁网站(有报告)。Javaee项目,springboot项目。
演示视频: 基于Springboot的高校汉服租赁网站(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构…...

分布式解决方案
目录 1. 分布式ID1-1. 传统方案1-2. 分布式ID特点1-3. 实现方案1-4. 开源组件 2. 分布式Session2-1. 传统Session2-2. Spring-Session2-3. Token Redis2-4. JWT2-5. 拦截器统一处理Token2-6. Oauth2 3. 分布式锁3-1. redis3-2. Zookeeper 1. 分布式ID 1-1. 传统方案 时间戳U…...

力扣刷题日记——L724. 寻找数组的中心下标
1. 前言 今天是力扣刷题日记的第二天,今天依旧是一道简单题啊,慢慢来,先看看题目是什么吧。 2. 题目描述 给你一个整数数组 nums ,请计算数组的 中心下标。 数组 中心下标 是数组的一个下标,其左侧所有元素相加的和…...

【Kotlin】类和对象
1 前言 Kotlin 是面向对象编程语言,与 Java 语言类似,都有类、对象、属性、构造函数、成员函数,都有封装、继承、多态三大特性,不同点如下。 Java 有静态(static)代码块,Kotlin 没有࿱…...

Docker完整版(一)
Docker完整版(一) 一、Docker概述1.1、Docker简介1.2、Docker的用途1.3、容器与虚拟机的区别1.4、Docker系统架构1.5、Docker仓库 二、Docker引擎2.1、Docker引擎架构2.2、Docker引擎分类2.3、Docker引擎的安装2.4、Docker镜像加速器 三、Docker镜像3.1、…...

AIOPS:Zabbix结合讯飞星火做自动化告警+邮件通知并基于人工智能提供解决方案
目前Zabbix官方已经提供Zabbix+ChatGPT的解决方案 ChatGPT一周年,你充分利用了吗?Zabbix+ChatGPT,轻松化解告警! 但是由于需要魔法等其他因素,比较不稳定,遂决定使用国内模型,这里我挑选的是讯飞星火,基于我之前的文档,在此基础上通过Zabbix的告警脚本实现调用AI模型…...

AHU 汇编 实验六
一、实验名称:实验6 输入一个16进制数,把它转换为10进制数输出 实验目的: 培养汇编中设计子程序的能力 实验过程: 源代码: data segmentbuff1 db Please input a number(H):$buff2 db 30,?,30 dup(?),13,10buff3 …...
Linux的输出、输入重定向和管道
目录 输出重定向 输入重定向 < << 管道操作 输出重定向 当我输⼊⼀个命令之后,回⻋,命令产⽣了结果,结果默认是输出到屏幕上的。 默认情况,⽆论⼀个命令执⾏正确与否,结果都会默认输出到屏幕上。 在有…...
java-新手笔记(枚举)
枚举(Enumeration)是一种特殊的类,用于表示固定数量的常量值。 枚举类型使得代码更加清晰,易于维护,同时也增加了类型安全。 这边使用一个枚举封装重要数据 enum Day {SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FR…...

Centos7 安装postgresql14后无法连接数据库
1、数据库服务器允许外部访问5432端口。 2、postgresql.conf 3、pg_hba.conf a、制定某个IP(192.168.0.107)访问 b、指定ip段访问 允许10.1.1.0~10.1.1.255网段登录数据库 host all all 10.1.1.0/24 trust c、指定全网访问 host a…...

GaussDB(DWS)运维利刃:TopSQL工具解析
在生产环境中,难免会面临查询语句出现异常中断、阻塞时间长等突发问题,如果没能及时记录信息,事后就需要投入更多的人力及时间成本进行问题的定位和解决,有时还无法定位到错误出现的地方。在本期《GaussDB(DWS)运维利刃࿱…...

信息安全、网络安全以及数据安全三者之间的区别
随着信息技术的飞速发展,网络安全、信息安全、数据安全等词汇在平时出现的频率越来越高,尤其是数据安全,是大家都关心的一个重要话题。事实上,有很多人对网络安全、信息安全、数据安全的概念是区分不清的,下面由我帮大…...

初阶数据结构之---堆的应用(堆排序和topk问题)
引言 上篇博客讲到了堆是什么,以及堆的基本创建和实现,这次我们再来对堆这个数据结构更进一步的深入,将讲到的内容包括:向下调整建堆,建堆的复杂度计算,堆排序和topk问题。话不多说,开启我们今…...
架构师面试100问?
面试架构师时,需要考察广泛的知识领域,包括技术、架构设计、团队管理、沟通能力等方面。以下是一些可能的面试问题,涵盖了多个方面问题: 介绍一下你的技术背景和经验。你在之前的项目中扮演过哪些角色?你对微服务架构…...

visualization_msgs::Marker 的pose设置,map坐标系的3d box显示问题
3D框显示 3D框显示可以使用visualization_msgs::Marker::LINE_LIST或者LINE_STRIP,前者使用方法需要指明线的两个端点,后者自动连接相邻两个点。 姿态问题 网上看了一些,没有涉及到朝向设置,Pose.orientation默认构造为4个0 至…...
c语言:输入定制
输入定制 任务描述 输入数据是一大串数字,要求读取五个数,但要求你只处理其中的第1、3、5个数,输出这三个数的和。第一个数只读1位数,第二个数只读2位数,第三个数只读3位数,第四个数只读4位数,…...

Python批量提取Word文档表格数据
在大数据处理与信息抽取领域中,Word文档是各类机构和个人普遍采用的一种信息存储格式,其中包含了大量的结构化和半结构化数据,如各类报告、调查问卷结果、项目计划等。这些文档中的表格往往承载了关键的数据信息,如统计数据、项目…...

【Qt】四种绘图设备详细使用
绘图设备有4个: 绘图设备是指继承QPainterDevice的子类—QPixmap QImage QPicture QBitmap(黑白图片) QBitmap——父类QPixmapQPixmap图片类,主要用来显示,它针对于显示器显示做了特殊优化,依赖于平台的,只能在主线程中使用(UI线…...
区块链web3智能合约Solidity学习资源整理
简单说明: Solidity 是一门面向合约的、为实现智能合约而创建的高级编程语言。这门语言受到了 C,Python 和 Javascript 语言的影响,设计的目的是能在以太坊虚拟机(EVM)上运行。 Solidity中文官方文档: ht…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...