首页 > 其他分享 >unordered_map的理解和应用

unordered_map的理解和应用

时间:2024-04-08 16:11:07浏览次数:19  
标签:std map 理解 键值 key my unordered

1、介绍

unordered_map,它是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能。

1.1、特性

  1. 关联性:通过key去检索value,而不是通过绝对地址(和顺序容器不同)
  2. 无序性:使用hash表存储,内部无序
  3. Map : 每个值对应一个键值
  4. 键唯一性:不存在两个元素的键一样
  5. 动态内存管理:使用内存管理模型来动态管理所需要的内存空间

由于unordered_map内部采用的hashtable的数据结构存储,所以,每个特定的key会通过一些特定的哈希运算映射到一个特定的位置,我们知道,hashtable是可能存在冲突的(多个key通过计算映射到同一个位置),在同一个位置的元素会按顺序链在后面。所以把这个位置称为一个bucket是十分形象的(像桶子一样,可以装多个元素)。

    

 unordered_map内部其实是由很多哈希桶组成的,每个哈希桶中可能没有元素,也可能有多个元素。

1.2、模板

1 template < class Key,                                    // 键值对中键的类型
2            class T,                                      // 键值对中值的类型
3            class Hash = hash<Key>,                       // 容器内部存储键值对所用的哈希函数
4            class Pred = equal_to<Key>,                   // 判断各个键值对键相同的规则
5            class Alloc = allocator< pair<const Key,T> >  // 指定分配器对象的类型
6            > class unordered_map;

主要使用的也是模板的前2个参数<键,值>

unordered_map<const Key, T> map;
参数含义
<key,T> 前 2 个参数分别用于确定键值对中键和值的类型,也就是存储键值对的类型。
Hash = hash<Key> 用于指明容器在存储各个键值对时要使用的哈希函数,默认使用 STL 标准库提供的 hash<key> 哈希函数。注意,默认哈希函数只适用于基本数据类型(包括 string 类型),而不适用于自定义的结构体或者类。
Pred = equal_to<Key> 要知道,unordered_map 容器中存储的各个键值对的键是不能相等的,而判断是否相等的规则,就由此参数指定。默认情况下,使用 STL 标准库中提供的 equal_to<key> 规则,该规则仅支持可直接用 == 运算符做比较的数据类型。

1.3、unordered_map的构造函数

(1)默认构造函数:

unordered_map<int, string> mymap;

(2)使用n个元素构造unordered_map:

unordered_map<int, string> mymap = {{1, "one"}, {2, "two"}, {3, "three"}};

(3)使用给定的范围构造unordered_map:

1 vector<pair<int, string>> myVector = {{1, "one"}, {2, "two"}, {3, "three"}};  
2 unordered_map<int, string> mymap(myVector.begin(), myVector.end());

(4)使用给定的哈希函数和相等比较函数构造unordered_map:

 1 struct myHashFunction {  
 2     size_t operator()(const int& key) const {  
 3         return hash<int>()(key);  
 4     }  
 5 };  
 6   
 7 struct myEqualFunction {  
 8     bool operator()(const int& key1, const int& key2) const {  
 9         return key1 == key2;  
10     }  
11 };  
12   
13 unordered_map<int, string, myHashFunction, myEqualFunction> mymap;

2、unordered_map的函数应用

成员方法功能
begin() 返回指向容器中第一个键值对的正向迭代器。
end()  返回指向容器中最后一个键值对之后位置的正向迭代器。
cbegin() 和 begin() 功能相同,只不过在其基础上增加了 const 属性,即该方法返回的迭代器不能用于修改容器内存储的键值对。
cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,即该方法返回的迭代器不能用于修改容器内存储的键值对。
empty() 若容器为空,则返回 true;否则 false。
size() 返回当前容器中存有键值对的个数。

 

2.1、unordered_map迭代器的示例:

(1)使用迭代器遍历unordered_map,从begin()到end()。在循环中,使用it->first和it->second分别访问键和值。

 1 #include <iostream>  
 2 #include <unordered_map>    
 3 int main() {  
 4     std::unordered_map<int, std::string> mymap = {{1, "one"}, {2, "two"}, {3, "three"}};   
 5     // 使用迭代器遍历unordered_map  
 6     for (auto it = mymap.begin(); it != mymap.end(); ++it) {  
 7         std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;  
 8     }   
 9     return 0;  
10 }
11 //Key: 1, Value: one  
12 //Key: 2, Value: two  
13 //Key: 3, Value: three  

(2)使用范围for循环遍历unordered_map,这种方式更加简洁。使用const auto& pair来捕获每个键值对,并使用pair.first和pair.second分别访问键和值。

 1 #include <iostream>  
 2 #include <unordered_map>   
 3 int main() {  
 4     std::unordered_map<int, std::string> mymap = {{1, "one"}, {2, "two"}, {3, "three"}};   
 5     // 使用范围for循环遍历unordered_map  
 6     for (const auto& pair : mymap) {  
 7         std::cout << "Key: " << pair.first << ", Value: " << pair.second << std::endl;  
 8     }  
 9     return 0;  
10 }
11 //Key: 1, Value: one  
12 //Key: 2, Value: two  
13 //Key: 3, Value: three  

2.2、unordered_map的容量和访问函数

max_size() 返回容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。
operator[key] 该模板类中重载了 [] 运算符,其功能是可以向访问数组中元素那样,只要给定某个键值对的键 key,就可以获取该键对应的值。注意,如果当前容器中没有以 key 为键的键值对,则其会使用该键向当前容器中插入一个新键值对。
at(key) 返回容器中存储的键 key 对应的值,如果 key 不存在,则会抛出 out_of_range 异常。 
find(key) 查找以 key 为键的键值对,如果找到,则返回一个指向该键值对的正向迭代器;反之,则返回一个指向容器中最后一个键值对之后位置的迭代器(如果 end() 方法返回的迭代器)。
count(key) 在容器中查找以 key 键的键值对的个数。

(1)empty() 函数用于检查 unordered_map 是否为空,即是否不包含任何键值对。如果 unordered_map 为空,则返回 true;否则返回 false。

 1 #include <iostream>  
 2 #include <unordered_map>  
 3 int main() {  
 4     std::unordered_map<int, std::string> myMap;  
 5       
 6     if (myMap.empty()) {  
 7         std::cout << "myMap is empty" << std::endl;  
 8     } else {  
 9         std::cout << "myMap is not empty" << std::endl;  
10     }  
11       
12     myMap = {{1, "one"}, {2, "two"}, {3, "three"}};  
13       
14     if (myMap.empty()) {  
15         std::cout << "myMap is empty" << std::endl;  
16     } else {  
17         std::cout << "myMap is not empty" << std::endl;  
18     }  
19       
20     return 0;  
21 }
22 //myMap is empty  
23 //myMap is not empty

(2)size() 函数返回 unordered_map 中存储的键值对的数量。

 1 #include <iostream>  
 2 #include <unordered_map>  
 3   
 4 int main() {  
 5     std::unordered_map<int, std::string> myMap = {{1, "one"}, {2, "two"}, {3, "three"}};  
 6       
 7     std::cout << "Size of myMap: " << myMap.size() << std::endl;  
 8       
 9     return 0;  
10 }
11 //Size of myMap: 3

(3)operator[] 用于访问或修改指定键的值。如果键不存在,则会插入一个新的键值对,其中键为指定的键,值为该类型的默认值。

 1 #include <iostream>  
 2 #include <unordered_map>  
 3   
 4 int main() {  
 5     std::unordered_map<std::string, int> my_map;  
 6   
 7     // 使用operator[]插入键值对  
 8     my_map["apple"] = 1;  
 9     my_map["banana"] = 2;  
10   
11     // 使用operator[]访问键值对  
12     std::cout << "Apple: " << my_map["apple"] << std::endl;  
13     std::cout << "Banana: " << my_map["banana"] << std::endl;  
14   
15     // 如果键不存在,operator[]将插入新的键值对,并赋予默认值  
16     std::cout << "Orange: " << my_map["orange"] << std::endl;  
17   
18     return 0;  
19 }
20 //Apple: 1  
21 //Banana: 2  
22 //Orange: 0

(4)find方法用于查找具有指定键的元素

 1 std::unordered_map<Key, Value> my_map;  
 2 // 插入一些元素...  
 3   
 4 // 使用find方法查找具有指定键的元素  
 5 auto it = my_map.find("key");  
 6   
 7 if (it != my_map.end()) {  
 8     // 键存在于unordered_map中  
 9     std::cout << "Found key: " << it->first << ", value: " << it->second << std::endl;  
10 } else {  
11     // 键不存在于unordered_map中  
12     std::cout << "Key not found" << std::endl;  
13 }

(5)count方法用于获取具有指定键的元素的数量

 1 std::unordered_map<Key, Value> my_map;  
 2 // 插入一些元素...  
 3   
 4 // 使用count方法获取具有指定键的元素数量  
 5 size_t count = my_map.count("key");  
 6   
 7 if (count > 0) {  
 8     std::cout << "Key found" << std::endl;  
 9 } else {  
10     std::cout << "Key not found" << std::endl;  
11 }

(6)insert方法用于插入元素

 1 std::unordered_map<Key, Value> my_map;  
 2   
 3 // 使用insert方法插入元素  
 4 std::pair<std::unordered_map<Key, Value>::iterator, bool> result = my_map.insert({"key", "value"});  
 5   
 6 if (result.second) {  
 7     // 插入成功  
 8     std::cout << "Inserted key: " << result.first->first << ", value: " << result.first->second << std::endl;  
 9 } else {  
10     // 插入失败(键已存在)  
11     std::cout << "Key already exists" << std::endl;  
12 }
13 
14 //Inserted key: key, value: value

(7)erase方法用于删除元素

 1 std::unordered_map<Key, Value> my_map;  
 2 // 插入一些元素...  
 3   
 4 // 使用erase方法删除具有指定键的元素  
 5 auto it = my_map.find("key");  
 6 if (it != my_map.end()) {  
 7     my_map.erase(it);  
 8     std::cout << "Erased key: " << it->first << std::endl;  
 9 } else {  
10     std::cout << "Key not found" << std::endl;  
11 }
12 
13 //Erased key: key

(8)clear方法用于删除所有元素

 1 std::unordered_map<Key, Value> my_map;  
 2 // 插入一些元素...  
 3   
 4 // 使用clear方法删除所有元素  
 5 my_map.clear();  
 6   
 7 if (my_map.empty()) {  
 8     std::cout << "Map is empty" << std::endl;  
 9 } else {  
10     std::cout << "Map is not empty" << std::endl;  
11 }
12 
13 //Map is empty

(9)swap方法用于交换两个unordered_map对象的内容

 1 std::unordered_map<Key, Value> my_map1;  
 2 // 插入一些元素到my_map1...  
 3   
 4 std::unordered_map<Key, Value> my_map2;  
 5 // 插入一些元素到my_map2...  
 6   
 7 // 使用swap方法交换my_map1和my_map2的内容  
 8 my_map1.swap(my_map2);  
 9   
10 // 现在my_map1包含my_map2以前的元素,反之亦然

 

标签:std,map,理解,键值,key,my,unordered
From: https://www.cnblogs.com/Zhouce/p/18121538

相关文章

  • 并发工具类:ExecutorService、Future、CountDownLatch与Semaphore(第一章)
    目录一、引言ExecutorService与Future:优雅的任务提交与结果获取CountDownLatch:精确的线程同步点Semaphore:资源访问的流量控制器总结二、ExecutorService定义与接口概述生命周期管理高级特性与最佳实践使用ExecutorService时的常见注意事项与最佳实践建议一、引言......
  • mapper里不等号
    在MyBatis中,Mapper接口中不使用<>不等号进行SQL语句的编写,而是使用其他方式表示不等于。使用<和>进行转义:<转义为<>转义为>使用!=表示不等于。以下是一个Mapper接口的例子,展示了如何在select语句中使用不等号:<!--MapperXML--><mappernamespace="com.example.mappe......
  • (译) 理解 Elixir 中的宏 Macro, 第六部分:原地代码生成
    ElixirMacros系列文章译文[1](译)UnderstandingElixirMacros,Part1Basics[2](译)UnderstandingElixirMacros,Part2-MacroTheory[3](译)UnderstandingElixirMacros,Part3-GettingintotheAST[4](译)UnderstandingElixirMacros,Part4-Div......
  • (译) 理解 Elixir 中的宏 Macro, 第五部分:组装 AST
    ElixirMacros系列文章译文[1](译)UnderstandingElixirMacros,Part1Basics[2](译)UnderstandingElixirMacros,Part2-MacroTheory[3](译)UnderstandingElixirMacros,Part3-GettingintotheAST[4](译)UnderstandingElixirMacros,Part4-Div......
  • 模型代码理解本地知识库
    importosfromlangchain.chainsimportRetrievalQAfromlangchain_community.document_loadersimportTextLoaderfromlangchain_community.embeddingsimportOllamaEmbeddingsfromlangchain_community.llms.ollamaimportOllamafromlangchain_community.vectors......
  • Mapster (C# 对象映射器)
    参考:https://www.cnblogs.com/qiqigou/p/13696669.html官方文档:https://github.com/MapsterMapper/Mapster/wiki前言谈到对象映射器,AutoMapper知名度是非常的高,但很少有人知道Mapster。性能优于AutoMapper安装MapsterInstall-PackageMapster 或者 dotnetaddpackageM......
  • 手把手教你做阅读理解题-初中中考阅读理解解题技巧013-dearMars Project
    PDF格式公众号回复关键字:ZKYD013阅读理解技巧,在帮助读者有效获取和理解文本信息方面发挥着重要作用,熟练掌握如下6个技巧,可快速突破阅读理解1预览文章结构在开始深入阅读之前,快速浏览文章的标题、段落开头和结尾,可以迅速把握文章的主题、大致内容和结构标题通常能概括文章......
  • elasticsearch mapping
    1 概念:​ ES中的mapping有点类似与RDB中“表结构”的概念,在MySQL中,表结构里包含了字段名称,字段的类型还有索引信息等。在Mapping里也包含了一些属性,比如字段名称、类型、字段使用的分词器、是否评分、是否创建索引等属性,并且在ES中一个字段可以有对个类型。分词器、评分等概念在......
  • 解析for a in brr: print(“ “.join(map(str, a)))的作用
    #二维数组#a是一个列表#一共三个列表#所以三次换行forainbrr:print("".join(map(str,a)))这段代码是Python代码,它使用了一个循环来遍历列表`brr`中的每个元素`a`。在循环的每次迭代中,它将`a`转换为字符串,并通过空格连接起来,然后使用`print`函数打......
  • NET领域性能最好的对象映射框架Mapster使用方法
    Mapster是一个开源的.NET对象映射库,它提供了一种简单而强大的方式来处理对象之间的映射。在本文中,我将详细介绍如何在.NET中使用Mapster,并提供一些实例和源代码。和其它框架性能对比:Mapster的安装和配置:首先,打开VisualStudio并创建一个新的.NET项目。在NuGet包管理器控制台......