从根到叶:深入了解Map和Set

窗间映出一片高远的天空,

向晚的天际宁静而又清明。

我孤独的心灵在幸福地哭泣,

它在为天空如此美好而高兴。

恬静的晚霞一片火红,

晚霞灼烧着我的热情。

此刻的世界没有别人,

只有上帝,我和天空。

                                                                                                            ——(俄)吉皮乌斯《瞬间》

一.概念及场景

Map和Set是两种常见的数据结构,用于在编程中组织和存储数据。它们通常在不同的场景中使用,具有不同的特点和用途。

1.Map(映射)是一种将键(key)与值(value)相关联的数据结构。它提供了一种通过键快速查找值的方式。在Map中,每个键是唯一的,而值可以重复。

Map的场景

  •  数据索引和快速查找:Map允许通过键快速查找对应的值,因此在需要高效的数据检索和索引的场景中经常使用。例如,将学生的学号与其成绩关联起来,可以通过学号快速查找对应的成绩。
  • 数据去重:由于Map中的键是唯一的,可以利用这个特性进行数据的去重操作。例如,可以使用Map来统计一段文本中不同单词的出现次数,只保留每个单词的一个实例。

2.Set(集合)是一种存储独特元素的数据结构,其中每个元素都是唯一的。Set通常用于判断元素是否存在,而不关心元素的顺序。Set的实现通常基于哈希表或树结构。

Set的场景

  •  数据去重:由于Set中的元素是唯一的,可以使用Set来去除重复的数据。例如,从一个数组中去除重复的元素,可以通过将数组元素添加到Set中来实现。
  • 成员关系判断:Set提供了高效的成员关系判断操作。例如,可以使用Set来判断一个元素是否属于某个特定集合。

相关模型

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

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

总结
Map适用于需要将键与值相关联的场景,提供了快速的查找和索引功能。Set适用于存储唯一元素的场景,并提供了高效的成员关系判断。两者都在去重操作中有应用,但在其他的具体应用场景中,选择使用Map还是Set取决于具体的需求和数据结构的特点。

二.Map的说明及使用

2.1关于Map说明

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

Map的特点和操作

  1. 键-值对:Map中的数据以键-值对的形式进行存储。每个键都与一个特定的值相关联。
  2. 唯一键:Map中的键是唯一的,不允许重复。当尝试添加一个已经存在的键时,新的值会覆盖旧的值。
  3. 快速查找:Map提供了快速的查找功能,可以通过键来获取对应的值。这使得Map在需要高效的数据检索和索引的场景中非常有用。
  4. 增加和删除元素:可以向Map中添加新的键-值对,也可以删除已有的键-值对。
  5. 迭代:Map可以进行迭代操作,以便对其中的键-值对进行遍历和处理。

Map的常用方法说明:

2.2HashMap和TreeMap

HashMap和TreeMap是两种常见的Map实现,它们在底层数据结构和性能特点上有所区别。

HashMap

  • 底层数据结构:HashMap使用哈希表(Hash Table)作为底层数据结构,通过哈希函数将键映射到数组索引位置。
  • 键的存储顺序:HashMap中的键是无序存储的,即键的顺序不受插入顺序的影响。
  • 时间复杂度:平均情况下,HashMap提供常数时间复杂度(O(1))的查找、插入和删除操作。
  • 适用场景:HashMap适用于需要快速查找、插入和删除键值对,并不关心顺序的场景。它在大多数情况下具有较高的性能。

HashMap的使用:

代码案例:

import java.util.HashMap;public class HashMapExample {public static void main(String[] args) {// 创建HashMap实例HashMap<String, Integer> hashMap = new HashMap<>();// 插入键值对hashMap.put("apple", 10);hashMap.put("banana", 5);hashMap.put("orange", 8);hashMap.put("grapes", 15);hashMap.put("kiwi", 20);hashMap.put("mango", 12);// 获取值int appleCount = hashMap.get("apple");System.out.println("Number of apples: " + appleCount);// 检查键是否存在boolean containsKey = hashMap.containsKey("banana");System.out.println("Contains banana: " + containsKey);// 删除键值对hashMap.remove("orange");// 迭代键值对for (String key : hashMap.keySet()) {int value = hashMap.get(key);System.out.println(key + ": " + value);}}
}

 运行如下:

TreeMap

  • 底层数据结构:TreeMap使用红黑树(Red-Black Tree)作为底层数据结构,保持键的有序性。
  • 键的存储顺序:TreeMap中的键是按照键的自然顺序或自定义的比较器顺序进行排序的。
  • 时间复杂度:TreeMap提供O(log n)的时间复杂度的查找、插入和删除操作,其中n是键值对的数量。
  • 适用场景:TreeMap适用于需要按照键的顺序进行遍历和检索的场景。它可以用于范围查询,例如,查找最小键、最大键以及在两个键之间的键值对。

 TreeMap的使用:

import java.util.TreeMap;public class TreeMapExample {public static void main(String[] args) {// 创建TreeMap实例TreeMap<String, Integer> treeMap = new TreeMap<>();// 插入键值对treeMap.put("apple", 10);treeMap.put("banana", 5);treeMap.put("orange", 8);treeMap.put("grapes", 15);treeMap.put("kiwi", 20);treeMap.put("mango", 12);// 获取值int appleCount = treeMap.get("apple");System.out.println("Number of apples: " + appleCount);// 检查键是否存在boolean containsKey = treeMap.containsKey("banana");System.out.println("Contains banana: " + containsKey);// 删除键值对treeMap.remove("orange");// 迭代键值对for (String key : treeMap.keySet()) {int value = treeMap.get(key);System.out.println(key + ": " + value);}}
}

运行如下:

 HashMap和TreeMap的区别:

底层数据结构:

  • HashMap使用哈希表(数组+链表/红黑树)实现,通过哈希函数将键映射到数组索引位置,解决哈希冲突使用链表或红黑树。
  • TreeMap使用红黑树实现,保持键的有序性,每个节点都遵循二叉搜索树的性质。

插入和查找操作性能:

  • HashMap的插入和查找操作的平均时间复杂度为O(1),即常数时间复杂度。但在发生哈希冲突时,性能可能会下降,需要通过链表或红黑树进行顺序查找,最坏情况下的时间复杂度为O(n)。
  • TreeMap的插入和查找操作的时间复杂度为O(log n),其中n是元素的数量。由于使用红黑树作为底层数据结构,保持有序性,因此查找操作更加高效。

排序特性:

  • HashMap不保持键的有序性,键的顺序是不确定的。
  • TreeMap根据键的自然顺序或自定义比较器对键进行排序,提供有序的键值对遍历。

存储空间:

  • HashMap在内部使用数组来存储键值对,不保证顺序,因此通常占用较少的存储空间。
  • TreeMap使用红黑树作为底层数据结构,保持键的有序性,因而在存储大量数据时占用的存储空间通常会更多。

参考下图: 

2.3关于Map.Entry<K, V>的说明

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

代码案例:

import java.util.HashMap;
import java.util.Map;public class MapExample {public static void main(String[] args) {// 创建一个HashMap实例Map<String, Integer> map = new HashMap<>();// 添加键值对到Map中map.put("apple", 10);map.put("banana", 5);map.put("orange", 8);// 遍历Map中的条目for (Map.Entry<String, Integer> entry : map.entrySet()) {String key = entry.getKey();Integer value = entry.getValue();System.out.println("Key: " + key + ", Value: " + value);}// 获取指定键的值int appleCount = map.get("apple");System.out.println("Number of apples: " + appleCount);// 使用setValue()方法更新值int newBananaCount = 7;map.entrySet().stream().filter(entry -> entry.getKey().equals("banana")).findFirst().ifPresent(entry -> entry.setValue(newBananaCount));// 输出更新后的值int updatedBananaCount = map.get("banana");System.out.println("Updated number of bananas: " + updatedBananaCount);}
}

 运行如下:

注意 Map.Entry<K,V> 并没有提供设置 Key 的方法

 三.Set的说明及使用

 3.1关于Set说明

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

Set的特点和操作:

  1. 唯一性:Set中的元素是唯一的,不会出现重复的元素。如果尝试将重复的元素添加到Set中,它将被忽略。

  2. 无序性:Set中的元素没有特定的顺序。这意味着你不能通过索引来访问Set中的元素。如果需要按特定顺序遍历元素,可以将Set转换为列表或使用其他有序数据结构。

  3. 可变性:Set是可变的,可以添加或删除元素。可以通过添加新元素或删除现有元素来修改Set。

  4. 高效性:Set提供了高效的成员检查操作。由于Set使用了哈希表或类似的数据结构来实现,它可以在平均情况下以常量时间复杂度(O(1))执行插入、删除和查找操作。

  5. 迭代性:Set支持迭代操作,可以使用循环遍历Set中的所有元素。

  6. 数学集合操作:Set还支持常见的数学集合操作,例如并集、交集和差集。这些操作使得可以对Set进行合并、比较和筛选等操作。

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

 3.2TreeSet和HashSet

HashSet

  • 唯一性:HashSet中的元素是唯一的,不会存在重复元素。如果尝试将重复的元素添加到HashSet中,它将被忽略。

  • 无序性:HashSet中的元素没有特定的顺序。元素在HashSet中的存储位置是根据元素的哈希码计算得出的,并不与插入顺序或值的大小相关。

  • 元素存储:HashSet使用哈希表(Hash Table)来存储元素。哈希表通过哈希函数将元素的值映射到桶(bucket)中。每个桶可以包含一个或多个元素。通过哈希函数和桶的结构,HashSet实现了高效的插入、删除和查找操作。

  • 性能:HashSet的插入、删除和查找操作的平均时间复杂度是常数时间复杂度(O(1)),在大多数情况下具有很高的性能。但是,在某些情况下,由于哈希冲突(多个元素映射到同一个桶),性能可能会下降,导致操作的时间复杂度变为O(n)。

  • 迭代性:HashSet支持迭代操作,可以使用增强的for循环或迭代器来遍历HashSet中的所有元素。但是,由于HashSet是无序的,迭代顺序不可预测。

  • 对象比较:为了正确地判断元素的相等性,HashSet要求元素类正确实现equals()hashCode()方法。equals()方法用于比较两个元素的内容是否相等,而hashCode()方法用于计算元素的哈希码,以确定元素在哈希表中的存储位置。

import java.util.HashSet;
import java.util.Set;public class HashSetExample {public static void main(String[] args) {// 创建一个HashSet实例Set<String> set = new HashSet<>();// 添加元素到HashSetset.add("apple");set.add("banana");set.add("orange");// 输出HashSet的大小System.out.println("HashSet size: " + set.size());// 检查元素是否存在boolean containsOrange = set.contains("orange");System.out.println("Set contains 'orange': " + containsOrange);// 移除元素set.remove("banana");// 遍历HashSet中的元素System.out.println("HashSet elements:");for (String element : set) {System.out.println(element);}// 清空HashSetset.clear();// 检查HashSet是否为空boolean isEmpty = set.isEmpty();System.out.println("HashSet is empty: " + isEmpty);}
}

运行如下:

TreeSet:

  • 唯一性:TreeSet中的元素是唯一的,不会存在重复元素。如果尝试将重复的元素添加到TreeSet中,它将被忽略。

  • 排序性:TreeSet中的元素是有序的,根据元素的自然排序或指定的比较器排序。默认情况下,元素被按升序排序。

  • 元素存储:TreeSet使用红黑树数据结构进行存储。红黑树是一种自平衡的二叉搜索树,它通过保持树的平衡性,提供了高效的插入、删除和查找操作。元素在红黑树中根据其排序顺序进行存储。

  • 性能:TreeSet的插入、删除和查找操作的平均时间复杂度是O(log n),其中n是TreeSet中的元素数量。由于红黑树的平衡性,这些操作的性能相对稳定,不会受到元素的插入顺序的影响。

  • 迭代性:TreeSet支持迭代操作,可以使用增强的for循环或迭代器来遍历TreeSet中的所有元素。由于TreeSet是有序的,迭代顺序将按照元素的排序顺序进行。

  • 对象比较:为了正确地判断元素的相等性和排序顺序,TreeSet要求元素类实现Comparable接口或提供自定义的比较器。Comparable接口的compareTo()方法用于比较两个元素的顺序。

import java.util.TreeSet;
import java.util.Set;public class TreeSetExample {public static void main(String[] args) {// 创建一个TreeSet实例Set<String> set = new TreeSet<>();// 添加元素到TreeSetset.add("apple");set.add("banana");set.add("orange");// 输出TreeSet的大小System.out.println("TreeSet size: " + set.size());// 检查元素是否存在boolean containsOrange = set.contains("orange");System.out.println("Set contains 'orange': " + containsOrange);// 移除元素set.remove("banana");// 遍历TreeSet中的元素System.out.println("TreeSet elements:");for (String element : set) {System.out.println(element);}// 获取最小元素String firstElement = ((TreeSet<String>) set).first();System.out.println("First element: " + firstElement);// 获取最大元素String lastElement = ((TreeSet<String>) set).last();System.out.println("Last element: " + lastElement);}
}

 TreeSet和HashSet的区别:

结语:Map和Set是Java集合框架中常用的数据结构。Map是一种键值对的数据结构,用于存储和操作具有唯一键和对应值的元素,适用于缓存、数据索引和快速查找等场景。Set是一种无序、不重复元素的集合,用于存储和操作独立的元素,适用于去重和判断元素是否存在的场景。它们提供了高效的操作和查找能力,并有多个实现类可供选择,如HashMap、TreeMap、HashSet和TreeSet等,根据具体需求选择合适的实现类。

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

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

相关文章

SpringBlade error/list SQL 注入漏洞复现

0x01 产品简介 SpringBlade 是一个由商业级项目升级优化而来的 SpringCloud 分布式微服务架构、SpringBoot 单体式微服务架构并存的综合型项目。 0x02 漏洞概述 SpringBlade 框架后台 /api/blade-log/error/list路径存在SQL注入漏洞,攻击者除了可以利用 SQL 注入漏洞获取数…

让生活更加精致的APP?

晚上好&#xff0c;今天博主来介绍几款帮助你条理生活的APP&#xff0c;让你的生活更加精致&#xff0c;充满仪式感。 一&#xff0e;格志日记 一款以“格子”的方式记录日记的APP&#xff0c;非常简单明了&#xff0c;用户可以依据自己的喜好&#xff0c;来自由定义或者删除格…

SpringBoot实战项目——博客笔记项目

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、项目介绍二、项目的整体框架 2.1 数据库模块 2.2 前端模块 2.3 后端模块三、项目图片展示四、项目的实现 4.1 准备工作 4.…

【R语言实战】——金融时序分布拟合

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

Android audiotrack尾帧无声

前言 产品一直有用户反馈音频截断问题。在机遇巧合下现学现卖音频知识处理相关问题。 问题描述 我们查看以下简化播放器代码&#xff1a; class AACPlayer(private val filePath: String) {private val TAG "AACPlayer"private var extractor: MediaExtractor? …

TortoiseSVN 报错:The server unexpectedly closed the connetion

前言 CentOS7Linux 安装subversionmod_dav_svn&#xff0c;搭建subversion(svn)服务器 The server unexpectedly closed the connetion 解决办法 重启Apache服务 shell> systemctl restart httpd

uniapp—day02

个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大二在校生 &#x1f921; 个人主页&#xff1a;坠入暮云间x &#x1f43c;座右铭&#xff1a;给自己一个梦想&#xff0c;给世界一个惊喜。 &#x1f385;**学习目标: 坚持每一次的学习打卡 文章目录 WXML 和HTML区…

系统及其分类

系统定义 系统&#xff1a;指若干相互关联的事物组合而成的具有特定功能的整体。 系统的基本作用&#xff1a;对输入信号进行加工和处理&#xff0c;将其转换为所需要的输出信号。 系统分类 系统的分类错综复杂&#xff0c;主要考虑其数学模型的差异来划分不同类型。主要分为…

怎么绕过CDN查找真实IP

一、怎么绕过CDN查找真实IP 首先使用全球ping查看该域名是否存在cdn 方法一&#xff1a;使用phpinfo等探针的方式找到真实IP 方法二&#xff1a;网站根域或子域查找真实IP 大部分CDN服务都是按流量进行收费的&#xff0c;所以一些网站管理员只给重要业务部署CDN&#xff0c…

大华智慧园区综合管理平台 clientServer SQL注入漏洞复现

0x01 产品简介 “大华智慧园区综合管理平台”是一款综合管理平台,具备园区运营、资源调配和智能服务等功能。平台意在协助优化园区资源分配,满足多元化的管理需求,同时通过提供智能服务,增强使用体验。 0x02 漏洞概述 由于大华智慧园区综合管理平台clientServer接口处未…

使用reprepro+nginx搭建apt服务器

目录 项目背景 项目要求 项目开发过程 1、apt服务器的搭建 2、实现自定义指定源文件列表来实现apt update更新 3、实现软件启动时自动更新 4. source.list中镜像源地址的格式 项目开发的难点/坑点 总结 项目背景 前面写过一篇“利用Nginx搭建一个apt服务器”&#xff…

STM32嵌入式开发需要掌握硬件、嵌入式系统、C编程语言以及相关的外设驱动等知识

学习STM32嵌入式开发需要掌握硬件、嵌入式系统、C编程语言以及相关的外设驱动等知识。以下是学习STM32的路线及重要的学习内容&#xff1a; 阶段学习内容目标1.基础知识- 理解嵌入式系统的基本概念和原理 - 了解STM32系列微控制器的特点和应用领域掌握嵌入式系统基本概念&…

Midjourney绘图欣赏系列(十)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

用Docker Compose实现负载均衡【入门篇】

在本文中&#xff0c;我们将讨论如何使用Docker Compose管理多个容器&#xff0c;并实现负载均衡。 首先&#xff0c;让我们简要介绍一下Docker Compose。Docker Compose是一个用于定义和运行多个Docker容器的工具&#xff0c;通过一个单独的文件来描述应用程序的整个服务架构…

vue项目:webpack打包优化实践

本文目录 一、项目基本信息二、分析当前项目情况1、使用 webpack-bundle-analyzer 插件2、使用 speed-measure-webpack-plugin 插件 三、解决构建问题1、caniuse-lite 提示的问题2、 warning 问题 四、打包速度优化1、修改source map2、处理 loader 五、webpack性能优化1、使用…

idea+maven+tomcat+spring 创建一个jsp项目

概述&#xff1a;我真服了&#xff0c;这个垃圾学校还在教jsp&#xff0c;这种技术我虽然早会了&#xff0c;但是之前搞的大多都是springboot web类型的&#xff0c;这里我就复习一下&#xff0c;避免以后忘记这种垃圾技术 第一步&#xff1a;创建maven项目 第二步&#xff1a…

adb shell 指令集

1.connect device连接设备&#xff1a; adb devices #return: List of devices attached 0123456789ABCDEF device2.连接终端 adb shell从设备拷贝文件到本地 adb pull <remote> [local] 如: adb pull /sdcard/demo.txt e:\从到本地拷贝文件到设备 adb push &…

HUAWEI 华为交换机 配置 MAC 地址漂移检测示例

组网需求 如 图 2-17 所示&#xff0c;网络中两台 LSW 间网线误接形成了网络环路&#xff0c;引起 MAC 地址发生漂 移、MAC 地址表震荡。 为了能够及时检测网络中出现的环路&#xff0c;可以在 Switch 上配置 MAC 地址漂移检测功能&#xff0c; 通过检测是否发生MAC 地址漂移…

从零搭建Vue项目

目录 环境准备 NodeJS安装 ​编辑 2. 选择安装目录 3. 验证NodeJS环境变量 4. 配置npm的全局安装路径 5. 切换npm的淘宝镜像 6. 安装Vue-cli Vue项目创建 1. 打开UI界面 2. 打开项目管理器 3. 创建项目 vue项目目录结构介绍 运行vue项目 Vue项目开发流程 Vue组…

JAVA的多线程及并发

1. Java 中实现多线程有几种方法 继承 Thread 类&#xff1b; 实现 Runnable 接口&#xff1b; 实现 Callable 接口通过 FutureTask 包装器来创建 Thread 线程&#xff1b; 使 用 ExecutorService 、 Callable 、 Future 实 现 有 返 回 结 果 的多 线 程 &#xff08; 也 就 …