unordered_map元素访问和元素查找函数
1. operator[]
mapped_type& operator[] ( const key_type& k );
:
- 这个重载函数接受一个
const
引用类型的键(key_type
),并返回与该键关联的值(mapped_type
)的引用。 - 如果键(
k
)存在于unordered_map
中,它将返回该键的值的引用,允许你修改该值。 - 如果键(
k
)不存在,它将在unordered_map
中插入该键-值对,并返回一个默认构造的值的引用(通常为该类型的默认值)。 - 这意味着你可以通过
operator[]
来读取或修改unordered_map
中的值,而不需要显式地检查键是否存在或插入键-值对。
mapped_type& operator[] ( key_type&& k );
:
- 这个重载函数接受一个右值引用类型的键(
key_type
),并返回与该键关联的值(mapped_type
)的引用。 - 与第一个重载函数类似,如果键(
k
)存在于unordered_map
中,它将返回该键的值的引用,允许你修改该值。 - 如果键(
k
)不存在,它将在unordered_map
中插入该键-值对,并返回一个默认构造的值的引用。
以下是使用std::unordered_map
的operator[]
重载函数的示例:
#include <iostream> #include <unordered_map> int main() { std::unordered_map<std::string, int> myMap; // 使用 operator[] 插入键-值对 myMap["apple"] = 3; myMap["banana"] = 2; myMap["cherry"] = 5; // 访问键的值并修改它 std::cout << "Number of apples: " << myMap["apple"] << std::endl; myMap["apple"] = 4; // 访问不存在的键,会插入默认值并返回引用 std::cout << "Number of oranges: " << myMap["orange"] << std::endl; // 使用右值引用的 operator[] 插入键-值对 std::string fruit = "grape"; myMap[std::move(fruit)] = 6; // 遍历输出所有键-值对 for (const auto& kv : myMap) { std::cout << kv.first << ": " << kv.second << std::endl; } return 0; }
在这个示例中,我们使用operator[]
插入键-值对,访问并修改已存在的键的值,以及访问不存在的键,它会自动插入默认值。还演示了使用右值引用的operator[]
来插入新的键-值对。最后,我们遍历输出了所有键-值对。
2. at
- 修改值的
at
函数:
mapped_type& at(const key_type& k); mapped_type& at(key_type&& k);
- 这两个重载版本允许你根据键
k
修改关联容器中的值。如果键k
存在于容器中,它会返回对应的值的引用,允许你修改这个值。如果键k
不存在,它会抛出std::out_of_range
异常。
示例代码:
std::unordered_map<std::string, int> myMap; myMap["apple"] = 3; // 使用 at 函数修改值 myMap.at("apple") = 4;
- 如果键
"apple"
存在,它将修改值为4
。 - 只读访问值的
at
函数:
const mapped_type& at(const key_type& k) const;
- 这个重载版本允许你只读访问容器中的值。它返回与键
k
相关联的值的常量引用。如果键k
不存在,它也会抛出std::out_of_range
异常。
示例代码:
std::unordered_map<std::string, int> myMap; myMap["apple"] = 3; // 使用 at 函数只读访问值 int numberOfApples = myMap.at("apple");
- 如果键
"apple"
存在,它将返回值3
,并且你可以将其存储在变量numberOfApples
中。
总之,at
函数是一个用于安全地访问关联容器中元素的方法,因为它会检查键是否存在并在必要时抛出异常。这有助于避免访问不存在的键而导致的未定义行为。
3. find
- 非常量容器的
find
函数:
iterator find(const key_type& k);
- 这个版本的
find
函数用于非常量容器,返回一个迭代器(iterator)。如果容器中存在键k
,则迭代器指向与键k
相关联的元素;如果键k
不存在,它返回容器的end()
迭代器,表示未找到。
示例代码:
std::unordered_map<std::string, int> myMap; myMap["apple"] = 3; // 使用 find 函数查找键 "apple" auto it = myMap.find("apple"); if (it != myMap.end()) { // 找到了,输出值 std::cout << "Value of 'apple': " << it->second << std::endl; } else { // 未找到 std::cout << "Key 'apple' not found." << std::endl; }
- 常量容器的
find
函数:
const_iterator find(const key_type& k) const;
- 这个版本的
find
函数用于常量容器,返回一个常量迭代器(const_iterator)。它的功能与非常量版本相同,但不允许修改容器中的元素。
示例代码:
const std::unordered_map<std::string, int> myMap = { {"apple", 3}, {"banana", 2}, {"cherry", 5} }; // 使用 const find 函数查找键 "banana" auto it = myMap.find("banana"); if (it != myMap.end()) { // 找到了,输出值 std::cout << "Value of 'banana': " << it->second << std::endl; } else { // 未找到 std::cout << "Key 'banana' not found." << std::endl; }
总之,find
函数是一个用于在关联容器中查找特定键的非常有用的方法。如果你需要查找键是否存在并访问与之关联的值,find
函数是一个安全且高效的选择。
4. count
size_type count(const key_type& k) const;
k
:要查找的键。size_type
:返回值类型,通常是一个无符号整数类型,表示键k
在容器中的出现次数。
count
函数会在容器中查找键 k
,并返回键的出现次数。如果键 k
存在于容器中,count
函数将返回 1 或更大的正整数,表示键出现的次数。如果键 k
不存在,函数将返回 0,表示键没有出现。
示例代码:
std::unordered_map<std::string, int> myMap = { {"apple", 3}, {"banana", 2}, {"cherry", 5} }; // 计算键 "apple" 在容器中的出现次数 size_t appleCount = myMap.count("apple"); std::cout << "The count of 'apple': " << appleCount << std::endl; // 计算键 "grape" 在容器中的出现次数 size_t grapeCount = myMap.count("grape"); std::cout << "The count of 'grape': " << grapeCount << std::endl;
在上面的示例中,count
函数首先计算键 “apple” 在容器中的出现次数(应为 1),然后计算键 “grape” 在容器中的出现次数(应为 0)。count
函数对于检查某个键是否存在于容器中以及统计键的出现次数非常有用。如果你需要知道某个键是否存在以及它出现了多少次,可以使用 count
函数进行查询。
5. equal_range
pair<iterator,iterator> equal_range ( const key_type& k ); pair<const_iterator,const_iterator> equal_range ( const key_type& k ) const;
k
:要查找的键。pair
:返回值类型,一个包含两个迭代器的容器,表示范围的起始和结束位置。iterator
和const_iterator
:迭代器类型,表示容器的迭代器和常量迭代器。
equal_range
函数会在容器中查找键 k
,然后返回一个 pair
,其中第一个元素是指向范围的开始位置的迭代器,第二个元素是指向范围的结束位置的迭代器。这个范围包括了所有键等于 k
的元素。
示例代码:
std::map<int, std::string> myMap = { {1, "one"}, {2, "two"}, {2, "another two"}, // 注意:键 2 重复 {3, "three"} }; // 查找键 2 在容器中的范围 auto range = myMap.equal_range(2); // 输出范围中的元素 for (auto it = range.first; it != range.second; ++it) { std::cout << it->first << ": " << it->second << std::endl; }
在上面的示例中,equal_range
函数查找键 2 在 myMap
中的范围,并返回一个包含范围的起始和结束迭代器的 pair
。然后,我们使用迭代器遍历范围,输出范围中的元素。
equal_range
函数在处理关联容器中的重复键时非常有用,因为它允许你查找所有具有相同键的元素,并迭代遍历它们。
unordered_map修饰符函数
1. emplace
template <class... Args> pair<iterator, bool> emplace ( Args&&... args );
std::unordered_map
的 emplace
函数用于在哈希表中插入新的键值对,并返回一个 std::pair
,其中包含一个迭代器和一个布尔值。
Args&&... args
是模板参数包,允许你传递任意数量的参数。pair<iterator, bool>
是返回值类型,其中iterator
是插入或已存在键值对的迭代器,bool
表示插入是否成功。如果键已存在,则迭代器指向已存在的键值对,布尔值为false
;如果键不存在,则迭代器指向新插入的键值对,布尔值为true
。
以下是 emplace
函数的示例用法:
#include <iostream> #include <unordered_map> #include <string> int main() { std::unordered_map<int, std::string> myMap; // 使用 emplace 插入键值对 auto result1 = myMap.emplace(1, "One"); if (result1.second) { std::cout << "Insertion successful. Key: " << result1.first->first << ", Value: " << result1.first->second << std::endl; } else { std::cout << "Key already exists. Key: " << result1.first->first << ", Value: " << result1.first->second << std::endl; } // 尝试再次插入相同的键值对 auto result2 = myMap.emplace(1, "Another One"); if (result2.second) { std::cout << "Insertion successful. Key: " << result2.first->first << ", Value: " << result2.first->second << std::endl; } else { std::cout << "Key already exists. Key: " << result2.first->first << ", Value: " << result2.first->second << std::endl; } return 0; }
在上述示例中,首先使用 emplace
函数插入一个键值对,然后再次尝试插入相同的键值对。根据返回的布尔值可以确定插入是否成功,以及插入的键值对是已存在的还是新插入的。
2. emplace_hint
与 emplace
不同,emplace_hint
允许你提供一个提示位置,以提高插入操作的性能。
以下是对 emplace_hint
函数的参数和用法的简要说明:
position
:这是一个迭代器,它指示了插入位置的提示。新元素将插入到position
之前。这个参数可以帮助容器更高效地插入元素,但不是必需的。Args&&... args
:这是一个可变参数模板,用于传递新元素的构造参数。根据元素类型的构造函数,你可以传递任意数量的参数。- 返回值:
emplace_hint
返回一个迭代器,指向插入的新元素,或者如果插入失败,则返回一个指向容器中现有元素的迭代器。
下面是一个示例,演示了如何使用 emplace_hint
向 std::unordered_map
中插入新的键值对:
#include <iostream> #include <unordered_map> int main() { std::unordered_map<int, std::string> myMap; // 使用 emplace_hint 插入元素 auto hint = myMap.emplace_hint(myMap.begin(), 1, "One"); myMap.emplace_hint(hint, 2, "Two"); myMap.emplace_hint(hint, 3, "Three"); // 遍历 unordered_map 并打印键值对 for (const auto& pair : myMap) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; }
在这个示例中,emplace_hint
被用来插入新的键值对,通过 hint
提示位置,以提高插入的效率。注意,emplace_hint
可以在任何位置插入元素,但通常你会使用提示位置以避免不必要的搜索和移动操作。
3. insert
pair<iterator, bool> insert(const value_type& val)
:将一个键值对val
插入到unordered_map
中。如果插入成功,返回一个pair
,其中的iterator
指向插入的元素,bool
表示插入是否成功。
示例:
std::unordered_map<int, std::string> myMap; std::pair<int, std::string> pairToInsert(1, "One"); auto result = myMap.insert(pairToInsert); if (result.second) { std::cout << "Insertion successful." << std::endl; } else { std::cout << "Insertion failed (key already exists)." << std::endl; }
template <class P> pair<iterator, bool> insert(P&& val)
:使用移动语义,将一个键值对val
插入到unordered_map
中。同样返回一个pair
,表示插入结果。
示例:
std::unordered_map<int, std::string> myMap; auto result = myMap.insert(std::make_pair(1, "One")); if (result.second) { std::cout << "Insertion successful." << std::endl; } else { std::cout << "Insertion failed (key already exists)." << std::endl; }
iterator insert(const_iterator hint, const value_type& val)
:在给定的位置hint
处插入一个键值对val
。这个函数允许你提供一个位置提示,以提高插入效率。
示例:
std::unordered_map<int, std::string> myMap; auto hint = myMap.begin(); // 可以是任何迭代器位置 myMap.insert(hint, std::make_pair(1, "One"));
template <class P> iterator insert(const_iterator hint, P&& val)
:与第三个函数类似,使用移动语义插入键值对,同时提供位置提示。
示例:
std::unordered_map<int, std::string> myMap; auto hint = myMap.begin(); // 可以是任何迭代器位置 myMap.insert(hint, std::make_pair(1, "One"));
template <class InputIterator> void insert(InputIterator first, InputIterator last)
:用一对迭代器[first, last)
指定的范围内的元素插入到unordered_map
中。
示例:
std::unordered_map<int, std::string> myMap; std::vector<std::pair<int, std::string>> data = {{1, "One"}, {2, "Two"}, {3, "Three"}}; myMap.insert(data.begin(), data.end());
void insert(initializer_list<value_type> il)
:使用初始化列表中的元素插入到unordered_map
中。
示例:
std::unordered_map<int, std::string> myMap; myMap.insert({{1, "One"}, {2, "Two"}, {3, "Three"}});
这些函数提供了多种插入键值对的方式,使你可以根据需求选择最合适的方法。
4. erase
iterator erase(const_iterator position)
:通过迭代器位置position
删除对应键值对。返回指向删除元素之后位置的迭代器。
示例:
std::unordered_map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}}; auto it = myMap.find(2); // 找到键为2的位置 if (it != myMap.end()) { myMap.erase(it); // 删除键为2的元素 }
size_type erase(const key_type& k)
:通过键k
删除对应的键值对。返回删除的元素个数(0或1,因为键在unordered_map
中是唯一的)。
示例:
std::unordered_map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}}; size_t erased = myMap.erase(2); // 删除键为2的元素 std::cout << "Erased " << erased << " element(s)." << std::endl;
iterator erase(const_iterator first, const_iterator last)
:通过一对迭代器[first, last)
删除指定范围内的键值对。返回指向删除操作之后位置的迭代器。
示例:
std::unordered_map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}}; auto first = myMap.begin(); // 范围起始位置 auto last = myMap.find(2); // 范围结束位置,找到键为2的位置 if (last != myMap.end()) { myMap.erase(first, last); // 删除范围内的元素 }
这些函数提供了不同的方式来删除 unordered_map
中的元素,根据需求可以选择最合适的方法。
5. clear
void clear() noexcept;
:清空unordered_map
中的所有键值对。这个操作会使unordered_map
变为空,但不会改变容器的容量。
示例:
std::unordered_map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}}; std::cout << "Size before clear: " << myMap.size() << std::endl; myMap.clear(); // 清空 unordered_map std::cout << "Size after clear: " << myMap.size() << std::endl;
- 输出:
Size before clear: 3 Size after clear: 0
这个函数是一个无异常操作 (noexcept
),意味着它不会抛出异常。它可以在需要清空 unordered_map
的情况下使用,以释放容器占用的资源。
6. swap
void swap ( unordered_map& ump );
:交换当前unordered_map
与参数ump
所表示的unordered_map
的内容。这个操作不会改变容器的容量,只是交换它们的内容。
示例:
std::unordered_map<int, std::string> map1 = {{1, "One"}, {2, "Two"}}; std::unordered_map<int, std::string> map2 = {{3, "Three"}, {4, "Four"}}; std::cout << "map1 before swap:" << std::endl; for (const auto& pair : map1) { std::cout << pair.first << ": " << pair.second << std::endl; } std::cout << "map2 before swap:" << std::endl; for (const auto& pair : map2) { std::cout << pair.first << ": " << pair.second << std::endl; } map1.swap(map2); // 交换 map1 和 map2 的内容 std::cout << "map1 after swap:" << std::endl; for (const auto& pair : map1) { std::cout << pair.first << ": " << pair.second << std::endl; } std::cout << "map2 after swap:" << std::endl; for (const auto& pair : map2) { std::cout << pair.first << ": " << pair.second << std::endl; }
- 输出:
map1 before swap: 1: One 2: Two map2 before swap: 3: Three 4: Four map1 after swap: 3: Three 4: Four map2 after swap: 1: One 2: Two
这个函数非常有用,因为它可以在不需要创建临时对象的情况下,高效地交换两个 unordered_map
的内容。
unordered_map桶函数
1. bucket_count
bucket_count
函数用于获取 std::unordered_map
容器中当前桶(buckets)的数量。桶是哈希表中的存储位置,用于存储键值对。
size_type bucket_count() const noexcept;
size_type
:表示无符号整数类型,通常是size_t
。bucket_count()
:该函数没有参数。const
:表示该函数不会修改容器的内容。noexcept
:表示该函数不会抛出异常。
该函数返回当前 unordered_map
容器中桶的数量。
示例代码:
#include <iostream> #include <unordered_map> int main() { std::unordered_map<int, std::string> map; map[1] = "One"; map[2] = "Two"; map[3] = "Three"; map[4] = "Four"; std::cout << "Bucket count: " << map.bucket_count() << std::endl; return 0; }
在这个示例中,bucket_count
函数返回当前 std::unordered_map
中的桶数量,该数量取决于哈希函数和负载因子等因素。这个数量通常会比容器中实际的元素数量大,以确保元素能够均匀分布在桶中,从而提高查询性能。
2. max_bucket_count
max_bucket_count
函数用于获取 std::unordered_map
容器支持的最大桶(buckets)数量。桶是哈希表中的存储位置,用于存储键值对。
size_type max_bucket_count() const noexcept;
size_type
:表示无符号整数类型,通常是size_t
。max_bucket_count()
:该函数没有参数。const
:表示该函数不会修改容器的内容。noexcept
:表示该函数不会抛出异常。
该函数返回 std::unordered_map
容器支持的最大桶数量。这个值通常受到底层哈希表实现和系统资源限制的影响。
示例代码:
#include <iostream> #include <unordered_map> int main() { std::unordered_map<int, std::string> map; // 获取最大桶数量并输出 std::cout << "Max bucket count: " << map.max_bucket_count() << std::endl; return 0; }
在这个示例中,max_bucket_count
函数返回 std::unordered_map
容器支持的最大桶数量。这个值是由编译器和系统决定的,通常取决于系统的可用内存和哈希表实现。
3. bucket_size
bucket_size
函数用于获取指定桶中的元素数量,它需要传入一个桶的索引作为参数。
size_type bucket_size(size_type n) const;
size_type
:表示无符号整数类型,通常是size_t
。bucket_size(n)
:该函数接受一个参数n
,表示要查询的桶的索引。const
:表示该函数不会修改容器的内容。
这个函数返回指定桶中的元素数量。
示例代码:
#include <iostream> #include <unordered_map> int main() { std::unordered_map<int, std::string> map; // 插入一些键值对 map[1] = "one"; map[2] = "two"; map[3] = "three"; // 获取第一个桶中的元素数量 size_t bucketIndex = map.bucket(1); // 获取键为1的元素所在的桶的索引 size_t bucketSize = map.bucket_size(bucketIndex); // 获取该桶的元素数量 std::cout << "Bucket size for key 1: " << bucketSize << std::endl; return 0; }
在这个示例中,我们创建了一个 std::unordered_map
容器,插入了一些键值对,并使用 bucket_size
函数获取特定桶中的元素数量。请注意,我们首先使用 bucket
函数获取了键为1的元素所在的桶的索引。然后,我们使用 bucket_size
函数获取了该桶中的元素数量。
4. bucket
bucket
函数用于获取给定键所属的桶的索引,它需要传入一个键作为参数。
size_type bucket(const key_type& k) const;
size_type
:表示无符号整数类型,通常是size_t
。bucket(k)
:该函数接受一个参数k
,表示要查询的键。const
:表示该函数不会修改容器的内容。
这个函数返回指定键所属的桶的索引。
示例代码:
#include <iostream> #include <unordered_map> int main() { std::unordered_map<std::string, int> map; // 插入一些键值对 map["one"] = 1; map["two"] = 2; map["three"] = 3; // 获取键所属的桶的索引 size_t bucketIndex1 = map.bucket("one"); size_t bucketIndex2 = map.bucket("three"); std::cout << "Bucket index for key 'one': " << bucketIndex1 << std::endl; std::cout << "Bucket index for key 'three': " << bucketIndex2 << std::endl; return 0; }
在这个示例中,我们创建了一个 std::unordered_map
容器,插入了一些键值对,并使用 bucket
函数获取特定键所属的桶的索引。我们分别获取了键 “one” 和 “three” 所在的桶的索引。