Map和Set及其实现类详解

目录

一, 搜索

1,传统搜索

2,Map和Set模型

二, Map的使用

1,Map接口的继承及实现图

2,Map接口的使用

3,TreeMap和HashMap的使用和对比

1,TreeMap

代码示例

map中插入的数据按照key进行排序

map中插入的数据必须具有可比较性(或者实现了比较器相关接口)

​map中插入的值必须是唯一的,否则会进行覆盖

​通过Set> entrySet() 方法对map中的键值对进行遍历

将Map中的value全部分离出来存放在Collection中

 

2,HashMap

代码示例

3,TreeMap和HashMap的对比

三, Set的使用

1,Set接口的继承及实现图

2,Set接口的使用

3,TreeSet和HashSet的使用和对比

1,TreeSet

代码示例

Set存入的Key必须是唯一的,存入重复的Key会自动去重

​Set中不能插入为null的数据,否则会报空指针异常的错误

​Set中插入的Key必须具有可比较性

2,HashSet

四, 总结


一, 搜索

1,传统搜索

  • 直接遍历:时间复杂度是O(N),元素如果比较多的情况下效率会非常慢
  • 二分查找:时间复杂度是O(logN),但是搜索的前提是序列必须有序

这两种排序比较适合静态类型的查找(给定区间内的元素进行查找),一般不会对区间上的序列进行插入和删除了,而现实中的查找比如:

  • 根据姓名查找考试成绩
  • 通讯录,根据姓名查询联系方式
  • 不重复集合,需要先搜索关键字是否已经在集合中

这三种在查找时进行一些插入和删除的操作称为动态查找,上述的直接遍历和二分查找的方式就不太适合了,本篇博客介绍的Map和Set集合就是一种专门用来动态查找的集合容器.

2,Map和Set模型

一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称为Key-Value的键值对,所有模型有两种:

  1. 纯Key模型:
    1. 有一个英文词典,快速查找一个单词是否在词典中
    2. 快速查找某个名字在不在通讯录中
  2. Key-Value模型:
    1. 统计文件中每个单词出现的次数,统计结果是每个单词都与其对应的次数:<单词,单词出现的次数>
    2. 梁山好汉的江湖绰号:每个好汉都有自己的江湖绰号

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

二, Map的使用

Map是一个接口,该接口没有继承自Collection,该类中存储的是<K,V>结构的键值对,并且K一定是唯一的,不能重复.

1,Map接口的继承及实现图

  1. Map接口的实现类有两个,分别是TreeMap和HashMap
  2. TreeMap类实现了SortedMap接口(所以TreeMap中存入的key必须是可比较的,后面会说)

2,Map接口的使用

方法解释
V get (Object key)
返回 key 对应的 value
V getOrDefault (Object key, V defaultValue)
返回 key 对应的 value key 不存在,返回默认值
V put (K key, V value)
设置 key 对应的 value
V remove (Object key)
删除 key 对应的映射关系
Set<K> keySet ()
返回所有 key 的不重复集合
Collection<V> values ()
返回所有 value 的可重复集合
Set<Map.Entry<K, V>> entrySet ()
返回所有的 key-value 映射关系
boolean containsKey (Object key)
判断是否包含 key
boolean containsValue (Object value)
判断是否包含 value

注意:

Map接口没有继承Iterable接口,所以使用Map的对象不能直接进行遍历,需要先将其转换成Set对象再进行遍历,Map也提供了相应的方法对这种集合做特殊处理,就是Set<Map.Entry<K, V>> entrySet() 方法,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是一个接口,不能直接实例化对象,如果实例化对象只能实例化其实现类TreeMap或者HashMap
  • Map中存放键值对的Key是唯一的,value是可以重复的
  • Map中的Key可以全部分离出来,存储到Set中尽显访问(因为key不能重复,Set要求Key不能重复)
  • Map中的Value可以全部分离出来,存储在Collection的任何一个子集合中
  • Map中键值对的Key不能直接修改,value可以修改,同时存储两个相同的key的键值对时,后存储入Map的会覆盖之前存储入Map中的数据

3,TreeMap和HashMap的使用和对比

1,TreeMap

TreeMap的底层是红黑树(可以把它想象成比较复杂,性能更加优秀的搜索树),我们联想二叉搜索树的一些性能就可以理解TreeMap的一些性能了:

  • 二叉搜索树在插入的时候,对于已经在树中存在的数据是无法进行插入的,所以TreeMap中无法插入两个相同Key值的键值对
  • 二叉搜索树的左子树的数据永远小于相同根节点的右子树的数据,可知他是一棵有序树,TreeMap中的数据也是有序的,所以插入的数据必须具有可比较性,否则会报错(TreeMap是基于Key进行比较的)

代码示例

map中插入的数据按照key进行排序
    public static void main(String[] args) {Map<String,Integer> map = new TreeMap<>();map.put("hello",3);map.put("abc",4);System.out.println(map);}

map中插入的数据必须具有可比较性(或者实现了比较器相关接口)
//定义一个Student类 不实现比较器接口
class Student {}public static void main(String[] args) {Map<Student,Integer> map = new TreeMap<>();map.put(new Student(),3);
}
map中插入的值必须是唯一的,否则会进行覆盖
    public static void main(String[] args) {Map<String,Integer> map = new TreeMap<>();map.put("hello",3);map.put("hello",4);System.out.println(map);}
通过Set<Map.Entry<K, V>> entrySet() 方法对map中的键值对进行遍历
public static void main(String[] args) {Map<String,Integer> map = new TreeMap<>();map.put("hello",3);map.put("abc",4);map.put("def",2);Set<Map.Entry<String, Integer>> entries = map.entrySet();for (Map.Entry<String, Integer> x: entries) {System.out.println("key: " + x.getKey() + " 出现了: " + x.getValue() + "次!");}
}
将Map中的value全部分离出来存放在Collection中
    public static void main(String[] args) {Map<String,Integer> map = new TreeMap<>();map.put("hello",3);map.put("abc",4);map.put("def",2);Collection<Integer> values = map.values();System.out.println(values);}

2,HashMap

HashMap的底层是一个哈希桶(数组+链表/红黑树)的结构,查询的时间复杂度是O(1),所以一般HashMap的效率比较高,由于HashMap这个类并没有实现SortedMap这个接口,所以不要求插入的数据中的Key具有可比较性

代码示例

HashMap和TreeMap大部分的方法相同,可以参照TreeMap的代码进行练习,这里只演示HashMap可以插入不需要具有可比较性的数据的代码

class Student {}public static void main(String[] args) {Map<Student,Integer> map = new HashMap<>();map.put(new Student(),1);map.put(new Student(),2);System.out.println(map);
}

3,TreeMap和HashMap的对比

Map 底层结构
TreeMap
HashMap
底层结构
红黑树
哈希桶
插入 / 删除 / 查找时间
复杂度
O(logN)O(1)
是否有序
关于 Key 有序
无序
线程安全
不安全
不安全
插入 / 删除 / 查找区别
需要进行元素比较
通过哈希函数计算哈希地址
比较与覆写
key 必须能够比较,否则会抛出 ClassCastException异常
自定义类型需要覆写 equals 和 hashCode方法
应用场景
需要 Key 有序场景下
Key 是否有序不关心,需要更高的时间性能

三, Set的使用

Set与Map主要的不同有两点:Set是继承自Collection的接口类,Set中只存储了Key

1,Set接口的继承及实现图

  1. Set接口的实现类有两个,分别是TreeSet和HashSet
  2. TreeSet类实现了SortedSet接口,所以TreeSet中存入的key必须是可比较的
  3. Set实现了Iterable接口,所以可以对Set进行遍历

2,Set接口的使用

方法解释
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 中,可以达到去重的效果

小结:

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

3,TreeSet和HashSet的使用和对比

1,TreeSet

TreeSet的底层是红黑树(可以把它想象成比较复杂,性能更加优秀的搜索树),我们联想二叉搜索树的一些性能就可以理解TreeSet的一些性能了:

  • 二叉搜索树在插入的时候,对于已经在树中存在的数据是无法进行插入的,所以TreeSet中无法插入两个相同Key
  • 二叉搜索树的左子树的数据永远小于相同根节点的右子树的数据,可知他是一棵有序树,TreeSet中的Key也是有序的,所以插入的数据必须具有可比较性,否则会报错

代码示例

Set存入的Key必须是唯一的,存入重复的Key会自动去重
public static void main(String[] args) {Set<String> set = new TreeSet<>();set.add("hello");set.add("abc");set.add("abc");System.out.println(set);
}
Set中不能插入为null的数据,否则会报空指针异常的错误

    public static void main(String[] args) {Set<String> set = new TreeSet<>();set.add(null);System.out.println(set);}
Set中插入的Key必须具有可比较性
//定义一个Student类 该类不实现任何比较器接口
class Student {}public static void main(String[] args) {Set<Student> set = new TreeSet<>();set.add(new Student());System.out.println(set);
}

2,HashSet

HashSet和TreeSet大部分的方法相同,可以参照TreeMap的代码进行练习,这里只演示HashMap可以插入不需要具有可比较性的数据的代码

//定义一个Student类 该类不实现任何比较器接口
class Student {}public static void main(String[] args) {Set<Student> set = new HashSet<>();set.add(new Student());System.out.println(set);
}

四, 总结

Set和Map使用场景分析:

Set:存储的Key没有其对应的映射关系,且需要对数据进行去重

Map:存储的数据之间存在某种映射关系

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

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

相关文章

Echarts 折线图的详细配置过程

文章目录 折线图 简介配置步骤简易示例 折线图 简介 Echarts是一款基于JavaScript的开源可视化库&#xff0c;由百度开发和维护。它提供了丰富多样的图表类型&#xff0c;其中折线图是其中一种常用的图表类型。 折线图通过连接数据点所形成的折线来展示数据的变化趋势。在折线…

互联网3.0 数字原生——数物虚实多维细粒度泛在融合

随着计算机、宽带网、通信技术的飞速发展&#xff0c;互联网技术和软硬件系统也不断演进&#xff0c;催生了一场前所未有的数字化革命。从Web1.0到Web3.0&#xff0c;以及虚拟现实、人工智能和数字孪生等领域的崛起&#xff0c;每一步都勾画出了一个崭新的数字未来&#xff0c;…

实战SpringMVC之CRUD

目录 一、前期准备 1.1 编写页面跳转控制类 二、实现CRUD 2.1 相关依赖 2.2 配置文件 2.3 逆向生成 2.4 后台代码完善 2.4.1 编写切面类 2.4.2 编写工具类 2.4.3 编写biz层 2.4.4 配置mapper.xml 2.4.5 编写相应接口类&#xff08;MusicMapper&#xff09; 2.4.6 处…

高效成绩查询系统助力,让学校管理事半功倍

各位老师们&#xff0c;大家好&#xff01;作为教育工作者&#xff0c;我们都了解成绩查询在学校管理中的重要性。然而&#xff0c;传统的查询方式往往繁琐耗时&#xff0c;给我们带来了不少困扰。因此&#xff0c;今天我将向大家介绍一个极其便捷的查询工具&#xff0c;能够帮…

生成式人工智能在高等教育 IT 中的作用

作者&#xff1a;Jared Pane 通过将你大学的数据与公共 LLMs 和 Elasticsearch 安全集成来找到你需要的答案。 根据 2023 年 4 月 EDUCAUSE 的一项调查&#xff0c;83% 的受访者表示&#xff0c;生成式人工智能将在未来三到五年内深刻改变高等教育。 学术界很快就询问和想象生…

盘点:人工智能发展趋势下的4大常见AI算法以及应用场景

近年来&#xff0c;人工智能的发展速度十分惊人&#xff0c;在安防监控、工业制造、农业、教育、金融、医疗等领域中的应用越来越广泛&#xff0c;并且未来几年也将继续保持高速的发展趋势。通过人工智能技术提高自动化程度、减少人工干预、提高监管效率&#xff0c;已经成为当…

虚拟机Ubuntu操作系统常用终端命令(2)(详细解释+详细演示)

本篇概要 本篇讲述了Ubuntu操作系统常用的几个功能&#xff0c;即超级用户&#xff0c;虚拟机系统损坏如何修复&#xff0c;用户和组&#xff0c;如何以root登录界面以及文件的权限方面的知识。希望能够得到大家的支持。 文章目录 本篇概要1.超级用户1.1使用超级用户1.2切换到…

【Robotframework+python】实现http接口自动化测试

前言 下周即将展开一个http接口测试的需求&#xff0c;刚刚完成的java类接口测试工作中&#xff0c;由于之前犯懒&#xff0c;没有提前搭建好自动化回归测试框架&#xff0c;以至于后期rd每修改一个bug&#xff0c;经常导致之前没有问题的case又产生了bug&#xff0c;所以需要…

Feign远程接口调用

概述 目的&#xff1a;解决微服务调用问题。如何从微服务A调用微服务B提供的接口。 特性&#xff1a; 声明式语法&#xff0c;简化接口调用代码开发。像调用本地方法一样调用其他微服务中的接口。集成了Eureka服务发现&#xff0c;可以从注册中心中发现微服务。集成了Spring…

一文详解TCP三次握手四次挥手

文章目录 TCP的三次握手和四次挥手三次握手四次挥手 TCP的三次握手和四次挥手 基本概念 SYN&#xff08;Synchronize Sequence Numbers&#xff0c;同步序列数字&#xff09;&#xff1a;用于建立连接的同步信号。 SYN 序列号的作用是用于标识每个数据包中的字节流的起始位置。…

Java基础入门·File类的使用

前言 ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ File类的创建方法 File类介绍 ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ …

docker 数据持久化

文章目录 定制镜像持久化需求实现 数据卷持久化数据卷简介数据卷的特性创建读写数据卷停止容器后的操作查看数据卷详情 创建只写数据卷查看数据卷详情 创建共享数据卷 Dockerfile持久化创建Dockerfile、构建和运行镜像查看宿主机端的目录 在容器层的 UnionFS&#xff08;联合文…

笔记1.2 计算机网络结构

网络边缘 主机、网络应用 接入网络&#xff0c;物理介质 有线或无线通信链路 网络核心&#xff08;核心网络&#xff09;&#xff1a; 互联的路由器&#xff08;或分组转发设备&#xff09; 网络之网络 一、网络边缘 主机&#xff08;端系统&#xff09;&#xff1a; 位…

vue3+ts+uniapp小程序封装获取授权hook函数

vue3tsuniapp小程序封装获取授权hook函数 小程序授权的时候&#xff0c;如果点击拒绝授权&#xff0c;然后就再也不会出现授权了&#xff0c;除非用户手动去右上角…设置打开 通过uni官方api自己封装一个全局的提示: uni.getSetting :http://uniapp.dcloud.io/api/other/settin…

Java操作Influxdb2.x

本片文章不讲怎么安装&#xff0c;只讲安装后如何用JAVA代码操作库表 1.创建数据库2.为bucket添加TELEGRAF配置3.TELEGRAF配置参数说明4.配置数据库的访问权限API TOKENS5.JAVA代码操作库表5.1 yaml5.2 pom依赖5.3 config5.4 controller5.5 查询方法、结果集提取方法 1.创建数据…

SpringBoot-插件化以及springboot扩展接口

插件化常用的实现思路 spi机制&#xff0c;Service Provider Interface &#xff0c;是JDK内置的一种服务发现机制&#xff0c;SPI是一种动态替换扩展机制约定配置和目录&#xff0c;利用反射配合实现springboot中的Factories机制Java agent&#xff08;探针&#xff09;技术S…

JavaScript中的Generator函数及其使用方式

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Generator函数⭐ 创建Generator函数⭐ 调用Generator函数⭐ Generator函数的应用1. 异步编程2. 生成器&#xff08;Generator&#xff09; ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧…

老板要我开发一个简单的工作流引擎-读后感与补充

概述 最近读了一篇《老板要我开发一个简单的工作流引擎》 幽默风趣&#xff0c;干货较多&#xff0c;作为流程引擎的设计者、开发者、探索者&#xff0c;写的很好&#xff0c;合计自己的理解&#xff0c;对每个功能补充说明&#xff0c;对于流程引擎的应用场景&#xff0c;做出…

vue中slot,slot-scope,v-slot的用法和区别

slot用于设置标签的属性值(slot“title”)slot-scopev-slot slot <el-menu-item v-if"!navMenu.children" :key"navMenu.id" :index"navMenu.id " click"itemClick(navMenu)" ><span slot"title">{{ navMenu.…

无涯教程-JavaScript - N函数

描述 N函数返回一个转换为数字的值。 语法 N (value) 争论 Argument描述Required/OptionalValue 要转换的值或对值的引用。 N转换下表中列出的值。 Required 值 N的返回值一个数字那个数字日期,采用Microsoft Excel中可用的内置日期格式之一该日期的序列号 TRUE 1 FALSE…