【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常见哈希函数:

  • 直接定值法--(常用):取关键字的某个线性函数为散列地址:HashKey= 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>的说明:

Map.Entry<K, V> Map 内部实现的用来存放 <key, value> 键值对映射关系的内部类 ,该内部类中主要提供了 <key, value>的获取, value 的设置以及 Key 的比较方式。
方法解释
K getKey ()
返回 entry 中的 key
V getValue ()
返回 entry 中的 value
V setValue(V value)
将键值对中的 value 替换为指定 value
注意: Map.Entry<K,V> 并没有提供设置 Key 的方法

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 或者 HashMap
2. 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 中不能插入nullkey

源码:

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() + " ");}}
}

结语: 写博客不仅仅是为了分享学习经历,同时这也有利于我巩固自己的知识点,总结该知识点,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进。同时也希望读者们不吝啬你们的点赞+收藏+关注,你们的鼓励是我创作的最大动力!

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

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

相关文章

代理IP如何应对自动化测试和爬虫检测

目录 一、代理IP在自动化测试和爬虫中的作用 二、代理IP的优缺点分析 1.优点 2.缺点 三、应对自动化测试和爬虫检测的策略 1.选择合适的代理IP 2.设置合理的请求频率和间隔 3.模拟人类行为模式 4.结合其他技术手段 四、案例与代码示例 五、总结 在自动化测试和爬虫开…

LoadBalancer (本地负载均衡)

1.loadbalancer本地负载均衡客户端 VS Nginx服务端负载均衡区别 Nginx是服务器负载均衡&#xff0c;客户端所有请求都会交给nginx&#xff0c;然后由nginx实现转发请求&#xff0c;即负载均衡是由服务端实现的。 loadbalancer本地负载均衡&#xff0c;在调用微服务接口时候&a…

Stable Diffusion 模型下载:Comic Babes(漫画宝贝)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 条目内容类型大模型基础模型SD 1.5来源CIVITAI作者datmuttdoe文件名称comicBabes_v2.safet…

快速了解Redis

Redis是什么&#xff1f; Redis是一个数据库&#xff0c;是一个跨平台的非关系型数据库&#xff0c;Redis完全开源&#xff0c;遵守BSD协议。它通过键值对(Key-Value)的形式存储数据。 与传统数据库不同的是 Redis 的数据是存在内存中的 &#xff0c;也就是它是内存数据库&am…

布隆过滤器(做筛选器索引)

什么是布隆过滤器 布隆过滤器&#xff08;Bloom Filter&#xff09;是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。 它的优点是空间效率和查询时间都比一般的算法要好的多&#xff0c;缺点是…

GIS学习笔记(四):GIS数据可视化综合(矢量数据)

矢量数据 arcgis的主要可视化工具&#xff1a;属性 符号系统 符号系统 按类别 这里不会涉及到数字的大小因素&#xff0c;只是按照字符的分类去做可视化 “唯一值”的含义 “建筑年代”字段共有10个年份&#xff0c;一个年份也许有多个数据( eg.1990年的建筑有20个)&…

qt vs 编程 字符编码 程序从源码到编译到显示过程中存在的字符编码

理解字符编码&#xff0c;请参考&#xff1a;unicode ucs2 utf16 utf8 ansi GBK GB2312 CSDN博客 汉字&#xff08;或者说多字节字符&#xff09;的存放需求&#xff0c;是计算机中各种编码问题的最直接原因。如果程序不直接使用汉字&#xff0c;或间接在所有操作步骤中统一使…

rocketmq源码分析(一)broker启动remoting抽象

1. netty基础 2. broker启动 rocketmq-broker.puml startuml BrokerStartup -> BrokerStartup: createBrokerController BrokerStartup -> BrokerController : controller.initialize() 初始化BrokerController,new 出各种 NettyRemotingServer BrokerController ->…

使用Tokeniser估算GPT和LLM服务的查询成本

将LLM集成到项目所花费的成本主要是我们通过API获取LLM返回结果的成本&#xff0c;而这些成本通常是根据处理的令牌数量计算的。我们如何预估我们的令牌数量呢&#xff1f;Tokeniser包可以有效地计算文本输入中的令牌来估算这些成本。本文将介绍如何使用Tokeniser有效地预测和管…

人工智能|机器学习——Canopy聚类算法(密度聚类)

1.简介 Canopy聚类算法是一个将对象分组到类的简单、快速、精确地方法。每个对象用多维特征空间里的一个点来表示。这个算法使用一个快速近似距离度量和两个距离阈值T1 > T2 处理。 Canopy聚类很少单独使用&#xff0c; 一般是作为k-means前不知道要指定k为何值的时候&#…

vue 下载的插件从哪里上传?npm发布插件详细记录

文章参考&#xff1a; 参考文章一&#xff1a; 封装vue插件并发布到npm详细步骤_vue-cli 封装插件-CSDN博客 参考文章二&#xff1a; npm发布vue插件步骤、组件、package、adduser、publish、getElementsByClassName、important、export、default、target、dest_export default…

linux ,Windows部署

Linux部署 准备好虚拟机 连接好查看版本&#xff1a;java -version安装jdk 解压命令&#xff1a;tar -zxvf 加jdk的压缩文件名cd /etc 在编辑vim profile文件 在最底下写入&#xff1a; export JAVA_HOME/root/soft/jdk1.8.0_151&#xff08;跟自己的jdk保持一致&#xff0…

初窥机器学习

人工智能 近几年来&#xff0c;人工智能&#xff08;AI&#xff09;已成为家喻户晓的术语&#xff0c;我们在游戏、电影&#xff08;还记得J.A.R.V.I.S吗&#xff1f;&#xff09;和书籍中经常看到它的提及和描绘&#xff0c;但人工智能究竟是什么呢&#xff1f; 人工智能简单…

go语言添加代理

LiteIDE 工具->管理 https://mirrors.aliyun.com/goproxy/或https://goproxy.cn,direct 命令行 go env -w GOPROXYhttps://goproxy.cn,direct

前端页面访问后台hiveserver2,阶段性报错

1、运行环境 Windows11下安装VMware&#xff0c;VMware下安装CentOS7 Linux系统&#xff0c;三台虚拟机集群部署hadoop&#xff0c;安装hive&#xff1b; 在Linux下安装Eclipse&#xff0c;创建maven工程&#xff0c;使用hive-jdbc-2.3.2访问hiveserver2 2、在windows11下&…

​如何防止网络攻击?

应对不同类型网络攻击的最佳途径是“知己”、“知彼”&#xff0c;在了解它们的工作原理、能够识别其手段、方法及意图的前提下&#xff0c;找出针对性的应对文案。今天&#xff0c;就为大家总结以下防止不同类型网络攻击的有效方法&#xff0c;希望无论是对个人、还是企业和组…

字节跳动也启动春季校园招聘了(含二面算法原题)

字节跳动 - 春招启动 随着各个大厂陆续打响春招的响头炮&#xff0c;字节跳动也官宣了春季校园招聘的正式开始。 还是那句话&#xff1a;连互联网大厂启动校招计划尚且争先恐后&#xff0c;你还有什么理由不马上行动&#xff1f;&#xff01; 先来扫一眼「春招流程」和「面向群…

RabbitMQ - 07 - 通过注解创建队列和交换机

之前消息模型的实现,都是通过rabbitMQ Management 控制台来手动创建 queue 和 exchange 的 在项目开发中有两种方式通过代码声明 创建 一种是通过 Bean 方式,这种代码量较大 稍繁琐 一种是通过注解的方式声明 先编写消费者代码 通过注解绑定了 消息队列,交换机,还有 routin…

​LeetCode解法汇总1261. 在受污染的二叉树中查找元素

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给出一个满足下述规则的二叉树&#xff1…

小程序学习 1

pages/goods/search/home.wxml首页功能设定 1. loading入场 2. 下拉刷新 3. 搜索栏 4. 分类切换 5. 商品列表 6. 规格弹层 7. 加载更多 <view style"text-align: center; color: #b9b9b9" wx:if"{{pageLoading}}"><t-loading theme"circula…