Map和Set的介绍

文章介绍了Java中的Map和Set接口,它们作为数据容器,特别适合动态查找。Map是键值对存储,包括Map.Entry内部类用于表示键值对,而Set仅存储键且不允许重复。文章提到了Map的常用方法,如Map.Entry的get和set方法,并指出Set的底层实现通常基于Map。同时,文章讨论了Set的子类,如HashSet和TreeSet,以及它们的特点和使用场景。

目录

1、Map 和 Set 的概念

2、模型

3、Map 的学习

3.1 关于 Map.Entry,v>

3.2 Map 的常用方法

 4、Set 的常用方法 

5、 Map 和 Set 的注意点


1、Map 和 Set 的概念

Java 提供了 Map 和 Set 的接口,是一种专门用来进行搜索的容器或数据结构,而他搜索的效率与其具体实例化的子类有关,比如 TreeMap 和 HashMap 的搜索效率就不一样。

如果利用学习到现在的知识,我们要去找一个元素,可能会采取遍历这样的方式,那么时间复杂度是 O(n),也可也采取二分查找,时间复杂度能达到 O(logn), 但必须要求数据是有序的。

如上所说的比较适合静态的查找,也就是一般不会对里面的元素进行插入和删除操作了。

那么假设我要根据学生的学号,找出对应的姓名,或者我要根据学生这样的一个对象,找出他对应的学校相关信息,再或者通讯录中,根据姓名,找出电话。

这些例子是生活中经常会碰到的,也就是在查找时,会更新里面的数据,比如这个学生退学了,就删除掉,即动态查找,那么上述遍历呀,二分查找呀,就不合适了,而 Map 和 Set 是一种适合动态查找的集合容器。

2、模型

通俗来讲,你去吃火锅,有俩宫格的,和单宫格的,甚至多宫格的,那么放在编程里,一般把需要搜索的数据称为关键字 key,和关键字对应的称为值 value,将它称为 Key-value 的键值对,所以模型会有两种:

Key-value 模型:

比如有个XX火锅vip客户表,上面对应每个vip客户来消费的次数,即 <vip客户,消费次数>
比如每个身份证所对应的人,即 <身份证,人>
纯 Key 模型:

比如老师上网课,会议中出现了一个叫 篮球哥 的人,于是让班长看下这个班级中有没有篮球哥这个人。
比如当你情敌发了个动态,你会看看你女神有没有给他点赞。
通过两个模型例子来看啊,键值对,也就是说大部分是对应关系,而纯 key 模型,大部分在找是否存在这个key,具体我们后面再细说。

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


3、Map 的学习

3.1 关于 Map.Entry<K,V>


Map.Entry<K,V> 是 Map 内部实现用的来存放 <key,value> 键值对的内部类,可以理解成我们之前模拟实现链表时候里面的 Node 节点,也是一个内部类。

这个内部类中,主要提供了 <key,value> 的获取方法和 value 的设置:

方法    解释
K getKey()    返回当前 Entry<K,V>  对象中的 key
V getValue()    返回当前 Entry<K,V>  对象中的 value
V setValue(V value)    将键值对中的 value 进行替换指定的 value

注意:Entry<K,V> 并没有提供 key 的设置,key 的值一定是唯一的,不能重复!

3.2 Map 的常用方法

 4、Set 的常用方法 

 

5、 Map 和 Set 的注意点

Set 的底层是 Map 来实现的, 讲到后续会体现出来。

Map 没有继承 Iterator 所以不能返回迭代器,而 Set 继承了 Iterator 可以采用迭代器遍历:

 

Map 并没有继承 Collection,里面的 key 不能重复,而 Set 虽然继承了 Collection 但是底层实现还是 Map 所以 Set 中的 key 也不能重复。

HashSet 的基础上维护了一个双向链表来记实现Set接口的常用类有 TreeSet 和 HashSet,还有一个LinkedHashSet,LinkedHashSet是在录元素的插入次序。 

到这里先了解这么多,具体在后续的 TreeMap,TreeSet,HashMap,HashSet 会体现。
 


<think>好的,用户现在想了解C++中mapset的数据结构及用法,特别是它们的区别使用方法。我之前已经提供了一些关于哈希碰撞的详细回答,现在需要结合用户提供的四个引用内容来回答这个问题。首先,我需要仔细分析用户提供的引用内容,提取关键点,然后组织成一个清晰的结构。 首先,引用[1]展示了map的使用,包括自定义比较函数插入元素的示例。引用[2]提到了mapmultimap在统计次数排序中的应用。引用[3]详细说明了map的构造函数操作函数,比如初始化方法。引用[4]则比较了map/set与unordered系列在数据结构、迭代器性能上的不同。用户之前的问题是关于哈希碰撞的,现在转向了C++的mapset,所以需要确保回答不偏离当前问题。 接下来,我需要确定用户的需求。用户明确询问mapset的区别与使用方法,因此需要分点解释两者的数据结构、特性、使用场景,并给出代码示例。根据引用内容,mapset都是基于红黑树实现的,而unordered系列使用哈希表。需要强调有序无序容器的区别,以及各自的优缺点。 在结构上,可以分为以下几个部分:基本概念、底层数据结构、主要区别(元素类型、用途、性能、迭代器)、使用示例、与unordered系列的对比、选择建议。每个部分需要结合引用中的代码说明,比如引用[1]中的自定义比较函数,引用[3]的构造函数,引用[2]中的统计排序方法。 需要注意用户提供的引用中,mapset的构造函数操作函数是重要内容,需要简要说明。同时,引用[4]提到map/set是双向迭代器,而unordered系列是单向,这点需要指出。此外,用户可能关心如何选择两者,因此需要给出性能对比使用场景的建议。 还需要检查是否有遗漏的信息,比如set存储唯一元素,而map存储键值对,这些都是基本点。在代码示例部分,引用[1]引用[2]提供了map的使用示例,可以引用或简化这些代码来说明插入、遍历自定义排序的方法。 最后,生成相关问题时要确保问题覆盖用户可能感兴趣的扩展内容,比如性能优化、底层实现原理、高级用法等。整个回答需要符合用户要求的结构清晰,分点说明,使用中文,并正确应用LaTeX格式,如类名使用$map$,时间复杂度使用$O(\log n)$等。</think>#### C++中`map``set`的详解与对比 --- ### 一、数据结构与底层实现 1. **底层数据结构** - `map``set`均基于**红黑树(Red-Black Tree)**实现,具有自动排序特性,插入、删除、查找的时间复杂度为$O(\log n)$[^4]。 - `unordered_map``unordered_set`基于**哈希表(Hash Table)**,时间复杂度为$O(1)$(平均情况),但无序[^4]。 2. **核心特性** - `set`:存储唯一键值(Key),无重复元素。 - `map`:存储键值对(Key-Value),键唯一,值可重复。 - 二者均默认按**升序**排序,可通过自定义比较函数修改排序规则(如引用[1]中的`CustomCompare`)。 --- ### 二、主要区别 | 特性 | `set` | `map` | |---------------------|----------------------------------|----------------------------------| | **元素类型** | 仅键(Key) | 键值对(Key-Value) | | **用途** | 快速判断元素是否存在 | 通过键快速查找/修改关联值 | | **性能** | 插入/查找:$O(\log n)$ | 同`set`,但需额外存储值 | | **迭代器类型** | 双向迭代器(支持++/--操作)[^4] | 同`set` | --- ### 三、基本用法示例 #### 1. `set`的典型操作 ```cpp #include <set> #include <iostream> int main() { std::set<int, std::greater<int>> s; // 降序排序 s.insert(3); s.insert(1); s.insert(4); for (auto& num : s) { std::cout << num << " "; // 输出:4 3 1 } return 0; } ``` #### 2. `map`的典型操作(引用[1]扩展) ```cpp #include <map> #include <string> struct CustomCompare { bool operator()(const std::string& a, const std::string& b) const { return a > b; // 降序排序 } }; int main() { std::map<std::string, int, CustomCompare> myMap; myMap["apple"] = 1; myMap["banana"] = 2; myMap["cherry"] = 3; // 遍历输出:cherry:3, banana:2, apple:1 return 0; } ``` --- ### 四、高级功能 1. **自定义排序规则** - 通过模板参数传入比较函数(如`std::greater<T>`或自定义结构体,见引用[1][3])。 2. **迭代器与范围操作** - 支持`begin()`, `end()`, `find()`, `lower_bound()`等操作。 3. **构造函数与初始化**(引用[3]) - 支持空构造、迭代器范围构造、拷贝构造等: ```cpp std::map<int, std::string> m1; // 空构造 std::map<int, std::string> m2(m1.begin(), m1.end()); // 迭代器构造 std::map<int, std::string> m3 = m2; // 拷贝构造 ``` --- ### 五、与`unordered`系列的对比(引用[4]) | 特性 | `map/set`(红黑树) | `unordered_map/set`(哈希表) | |---------------------|-----------------------------|-------------------------------| | **排序性** | 有序 | 无序 | | **插入/查找时间** | $O(\log n)$ | $O(1)$(平均) | | **内存占用** | 较低(树结构) | 较高(哈希表需预分配桶) | | **适用场景** | 需要有序遍历或范围查询 | 仅需快速查找,不关心顺序 | --- ### 六、选择建议 - **需要排序或范围查询**:优先选择`map/set`(如统计频率后按值排序,见引用[2]中的`multimap`用法)。 - **高频插入/查找,无需排序**:选择`unordered_map/unordered_set`。 - **内存敏感场景**:权衡红黑树哈希表的内存开销。 --- ### 相关问题 1. 如何在`map`中实现按值(Value)排序? 2. `multiset``unordered_multiset`有什么异同? 3. 红黑树如何保证$O(\log n)$的时间复杂度? 4. 哈希表与红黑树在内存管理上的具体差异是什么? --- [^1]: `map`自定义排序规则实现 [^2]: `map`与`multimap`在数据统计中的应用 [^3]: `map`的构造函数与初始化方法 [^4]: 有序容器与无序容器的底层实现对比
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值