《java数据结构》--详解Map和Set

概念

Map和set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。在之前我们常见的搜索方式一般有两种:

  1. 一种是直接遍历,这种方法的时间复杂度为O(N),如果元素比较多的话效率会十分低下
  2. 另一种是二分查找,时间复杂度为O(logN),但是有局限性必须是有序的

这两种排序一般用在静态查找,在查找时一般不会进行插入和删除,但现实中我们需要的往往是动态查找,即在查找时会进行一些插入和删除操作。这时就要用到map和set了,这两个是一种适合动态查找的集合容器。

模型

在聊map和set之前我们要先聊一聊key模型和value模型,一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为Key-value的键值对,所以 模型会有两种:

1. 纯 key 模型,比如:

有一个英文词典,快速查找一个单词是否在词典中

快速查找某个名字在不在通讯录中

2. Key-Value 模型,比如:

统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数:<单词,单词出现的次数>

Map中存储的就是key-value的键值对,Set中只存储了Key。

Map

说明

Map是一个接口类,不能直接实例化,该类并不继承自Cllection,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素,并且Key一定是唯一的,不能重复。

Map.Entry<k,v>

Map.Entry 是Map内部实现的用来存放键值对映射关系的内部类,该内部类中主要提供了 的获取,value的设置以及Key的比较方式。

Map.Entry的主要作用就是将key和value组合起来方便之后打印

//注意:Map.Entry并没有提供设置Key的方法

Map的常用方法

  1.  Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类TreeMap或者HashMap
  2. Map中存放键值对的Key是唯一的,value是可以重复的
  3.  在Map中插入键值对时,key不能为空,否则就会抛NullPointerException异常,但是value可以为空
  4. Map中的Key可以全部分离出来,存储到Set中来进行访问(因为Key不能重复)。
  5. Map中的value可以全部分离出来,存储在Collection的任何一个子集合中(value可能有重复)。
  6. Map中键值对的Key不能直接修改,value可以修改,如果要修改key,只能先将该key删除掉,然后再来进行 重新插入。
  7. Map中不能存储重复的Key如果存入的Key在Map里有则会覆盖掉原来的Key和value

TreeMap的使用

TreeMap的底层是一颗搜索树,搜索树的插入需要通过key来比较大小的如下图案例:

我们再来思考一下,既然插入是通过key来比较的那么是不是就意味着,key一定是可以比较的,所以当key是自定义类型时一定要注意,key要可比较。

key的值不能是null

TreeMap的遍历

TreeMap的遍历分为调用keySet()方法遍历和entrySet()方法遍历两种:

keySet():

Map<String,Integer> map = new TreeMap<>();map.put("a",1);map.put("c",3);map.put("d",4);map.put("b",2);//在TreeMap的遍历中我们可以通过key利用get方法找到value//keySet(),的作用是返回所有 key 的不重复集合//所以set的泛型与key的数据类型一致,在本代码中为String类型Set<String> set = map.keySet();//返回所有map中的key存入Set集合中//set就是一个存放map中的key的集合//接下来利用forEach遍历//String为set中元素的类型,str里存的就是map里key的值//所以可以通过str找到valuefor (String str:set) {//通过map.get(str)来获得map里每一个key所对应的value值Integer a = map.get(str);//根据str的值找到对应的value存入a中System.out.println("key:" + str +"  "+ "val:" + a);}System.out.println(map);

运行结果

entrySet():

 Map<String,Integer> map = new TreeMap<>();//存放数据map.put("a",1);map.put("c",3);map.put("d",4);map.put("b",2);//当我们调用entrySet()时,Set的泛型类型应与Map.Entry的类型一致,即<String,Integer>//<String,Integer>就是<k,v>键值对Set<Map.Entry<String,Integer>> set = map.entrySet();//返回所有map中的 key-value 映射关系//存储在set中,set就是<String,Integer>的集合(<a,1>,<b,2>,<c,3>,<d,4>)//之后通过forEnch遍历//Map.Entry<String,Integer>就是set里元素的类型//m就是map里的每一个键值对<String,Integer>for (Map.Entry<String,Integer> m :set) {//因为m就是map里的每一个键值对<String,Integer>//所以直接输出m也可以//也可以利用get.Value和get.Key进行打印System.out.println(m);}

//hashmap会在之后的博客中讲到

Set

Set与Map主要的不同有两点:

  • Set是继承自Collection的接口类
  • Set中只存储了Key

Set的常用方法:

注意:

  1. Set是继承自Collection的一个接口类
  2. Set中只存储了key,并且要求key一定要唯一
  3. Set的底层是使用Map来实现的,其使用key与Object的一个默认对象作为键值对插入到Map中的
  4. Set最大的功能就是对集合中的元素进行去重
  5. 实现Set接口的常用类有TreeSet和HashSet,还有一个LinkedHashSet,LinkedHashSet是在HashSet的基础 上维护了一个双向链表来记录元素的插入次序。
  6. Set中的Key不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  7. Set中不能插入null的key
  8. 因为Set中的元素是不可重复的,所以Set一般用作去重

TreeSet

TreeSet里的元素是不可重复的,如下例子

那么为什么TreeSet里的元素不可被重复呢?其时TreeSet的底层是一个TreeMap,它的key值是你add的对象的类型,value值是一个默认的Object对象,而TreeMap的key值是不可被重复的

我们再来看看这个例子:

class Student implements Comparable<Student>{public String name;public Integer age;public Integer high;public Student(String name, Integer age, Integer high) {this.name = name;this.age = age;this.high = high;}@Overridepublic int compareTo(Student o){return -1;}public String toString(){return "name: " + this.name + " age: " + this.age + " high: " + this.high;}}
 Set<Student> set = new TreeSet<>();set.add(new Student("zhangsan",12,150));set.add(new Student("zhangsan",12,150));set.add(new Student("lisi",22,180));set.add(new Student("wangwu",32,178));for(Student student:set){System.out.println(student);}

怎么回事?不是说不能有重复元素吗,这里怎么输出了两个重复元素,其这只是我们认为的相同元素,编译器可不这样认为,我们并没有完全重写compareTo方法,编译器是通过比较他们存储的内存地址来比较他们是否不同,所以在编译器看来它们都是不同的元素。所以如果我们要想不让我们输出的数据重复,需要重写compareTo方法

接下来我们按照年龄比较:

可以看到并没有重复年龄的学生

到这里我们就聊完了,Map和Set有关的知识不止这些还有很多,博主会在之后的博客中在聊到,如果你有说明不懂或者一些其他的见解欢迎评论或者私信博主,也希望可以支持一下博主啦!!!

我们下一篇再见了

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

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

相关文章

Leecode---动态规划---打家劫舍 / 乘积最大子数组

动态规划法&#xff1a; 思路&#xff1a; &#xff08;1&#xff09;状态定义&#xff1a;dp[i]代表前i家能偷盗的最大金额 &#xff08;2&#xff09;状态初始化&#xff1a;如果只有一家&#xff0c;只能偷这家dp[0]nums[0]&#xff1b;如果有两家&#xff0c;因为是连通的&…

看图猜成语微信小程序源码

后台可以自行设置关卡、等级、也可以一键部署&#xff0c; 开通流量主之后实现躺赚&#xff0c;你懂得。 个人号也可以开通&#xff0c;审核一次性必过。 类目选择 教育&#xff0c;源码仅供您参考&#xff01; 源码下载 https://download.csdn.net/download/huayula/8938579…

【计算机毕业设计】基于SSM+Vue的网上花店系统【源码+lw+部署文档】

目录 目 录 1 绪论 1.1 选题背景 1.2 选题意义 1.3 研究内容 2 系统开发技术 2.1 Java语言 2.2 SSM框架 2.3 MYSQL数据库 2.4 Vue框架 3 系统分析 3.1可行性研究 3.1.1经济可行性 3.1.2时间可行性 3.1.3操作可行性 3.2系统性能分析 3.2.1系统易用性 3.2.2系统健壮性 3.2.3系统…

电脑没电关机,wsl和docker又挂了,附解决过程

如题&#xff0c;开了个会没带笔记本电源&#xff0c;点啊弄关机后docker打不开&#xff0c;我以为是docker坏了&#xff0c;结果docker报错&#xff1a; An unexpected error occurred while executing a WSL command. Either shut down WSL down with wsl --shutdown, and/or…

【蓝桥杯国赛】双指针

适用于以下的情境&#xff1a; ① 数组 / 字符串中&#xff0c;有多少个满足情况的连续区间。 ② 数组 / 字符串&#xff0c;合并。 【第十三届pythonB组试题&#xff1a;近似gcd】 1. 题目描述 2. 难度&#xff1a;⭐⭐⭐⭐ 3. 思考分析&#xff1a; 具体参考&#xff…

依据SAM大模型识别的英国农田(农业田野)边界(FIBOA)矢量数据集

简介 fiboa 是一项旨在提高农田边界数据互操作性和相关农业数据的合作计划。最近推出的 fiboa 不仅仅是一个规范&#xff0c;它还是一个全面的系统&#xff0c;包括符合规范的数据、不断完善规范的讨论以及积极促进其发展的活跃社区。本项目的重点是促进创建更多有关田地边界和…

黑马程序员——Spring框架——day03

目录&#xff1a; AOP AOP简介 问题导入AOP简介和作用【理解】AOP的应用场景为什么要学AOPAOP入门案例【重点】 问题导入AOP入门案例思路分析AOP入门案例实现AOP中的核心概念AOP工作流程【理解】 问题导入AOP工作流程AOP核心概念在测试类中验证代理对象AOP切入点表达式 问题导…

【python】爬虫记录每小时金价

数据来源&#xff1a; https://www.cngold.org/img_date/ 因为这个网站是数据随时变动的&#xff0c;用requests、BeautifulSoup的方式解析html的话&#xff0c;数据的位置显示的是“--”&#xff0c;并不能取到数据。 所以采用webdriver访问网站&#xff0c;然后从界面上获取…

C语言 指针——函数指针的典型应用:计算定积分

目录 梯形法计算函数的定积分 函数指针的典型应用 梯形法计算函数的定积分 函数指针的典型应用 用函数指针编写计算任意函数定积分的 通用 函数

Vivado 比特流编译时间获取以及FPGA电压温度获取(实用)

Vivado 比特流编译时间获取以及FPGA电压温度获取 语言 &#xff1a;Verilg HDL 、VHDL EDA工具&#xff1a;ISE、Vivado Vivado 比特流编译时间获取以及FPGA电压温度获取一、引言二、 获取FPGA 当前程序的编译时间verilog中直接调用下面源语2. FPGA电压温度获取&#xff08;1&a…

es的总结

es的collapse es的collapse只能针对一个字段聚合&#xff08;针对大数据量去重&#xff09;&#xff0c;如果以age为聚合字段&#xff0c;则会展示第一条数据&#xff0c;如果需要展示多个字段&#xff0c;需要创建新的字段&#xff0c;如下 POST testleh/_update_by_query {…

JVM学习-详解类加载器(一)

类加载器 类加载器是JVM执行类加载机制的前提 ClassLoader的作用 ClassLoader是Java的核心组件&#xff0c;所有的Class都是由ClassLoader进行加载的&#xff0c;ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部&#xff0c;转换为一个与目标类型对应的ja…

Java学习【String类详解】

Java学习【String类详解】 String的介绍及定义方式String类型的比较String类型的查找charAt()访问字符indexOf()查找下标 转化和替换数值和字符串转化大小写的转换字符串转数组格式化替换 字符串的拆分和截取split()拆分substring()截取trim()去除两边空格 StringBuilder和Stri…

苏州金龙客车为新疆哪吒车队提供车辆交车

2024年旅游旺季提前到来、时间延长&#xff0c;新疆旅游市场有望延续去年火爆态势。 近期&#xff0c;新疆哪吒运输服务有限公司&#xff08;以下简称“哪吒车队”&#xff09;订购的最新一批10辆苏州金龙海格高端旅游大巴在苏州金龙厂区正式交付。哪吒车队负责人伍亚丽笑容满…

SpringCloud学习笔记万字整理(无广版在博客)

在此感谢黑马程序员的SpringCloud课程 所有笔记、生活分享首发于个人博客 想要获得最佳的阅读体验&#xff08;无广告且清爽&#xff09;&#xff0c;请访问本篇笔记 认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐…

python的元组

元组与列表的区别 元组和列表非常相似。不同之处在于&#xff0c;外观上&#xff1a;列表是被 方括号 包裹起来的&#xff0c;而元组是被 圆括号 包裹起来的。本质上&#xff1a;列表里的元素可修改&#xff0c;元组里的元素是 不可以“增删改” 。 还有一个微妙的地方要注意…

MK SD NAND(贴片式SD卡)在电力AI模块中的应用案例

近期一位客户&#xff0c;在网上了解到我们SD NAND后联系到我们&#xff0c;经过一系列了解对比后&#xff0c;下单了我们的SD NAND产品。 这位客户是做电力AI模块的&#xff0c;他们的产品主要应用在电力行业。 电力AI模块是集成了人工智能技术的系统&#xff0c;专门设计用于…

微信小程序注册流程及APPID,APPSecret获取

1.注册微信小程序 注册链接&#xff1a;公众号 (qq.com) 1.1填写邮箱、密码、验证码 1.2邮箱登录点击邮件中链接激活&#xff0c;即可完成注册 1.3用户信息登记 接下来步骤&#xff0c;将用个人主题类型来进行演示 填写主体登记信息&#xff0c;使用管理员本人微信扫描二维码…

离线环境下安装NVIDIA驱动、CUDA(HUAWEI Kunpeng 920 + NVIDIA A100 + Ubuntu 20.04 LTS)

文章目录 前言 一、基础环境 1.1、处理器型号 1.2、英伟达显卡型号 1.3、操作系统 1.4、软件环境 二、取消内核自动升级 2.1、查看正在使用的内核版本 2.2、查看正在使用的内核包 2.3、禁止内核更新 三、配置本地apt源 3.1、挂载iso镜像文件 3.2、配置apt源 3.3、…

python分别保存聚类分析结果+KeyError: ‘CustomerID‘报错

如何在完成聚类分析后按聚类编号保存数据并且带上原数据所属ID # 将每个聚类的数据保存到不同的文件中 for cluster_id in range(6): # 假设共有6个聚类cluster_data data[data[cluster] cluster_id]cluster_data_with_customer_id cluster_data.copy()cluster_data_with_…