无序关联容器 (STL)

C++程序设计语言中，`unordered_map`、`unordered_multimap`、`unordered_set`、`unordered_multiset`是标准模板库（STL）提供的一类无序关联容器（unordered associative containers）。是通过哈希表实现的数据结构。无序是指元素的名字（或者键值）的存储是无序的；这与用平衡二叉树实现的元素名字是有序存储的“关联容器”是相对概念。

## 历史

SGI的STL提供了`hash_map`, `hash_set`, `hash_multimap`, `hash_multiset`等类模板。由于其有用性，很快其它的C++编译器也支持了这一特性，如GCC、 libstdc++ 以及MSVC （在stdext命名空间）。

C++ TR1语言标准中提出了增加`hash_*`类模板，最终接受为`unordered_*`。Boost C++ Libraries也提供了一种实现。`<boost/unordered_map.hpp>`.

## 类成员函数

头文件`<unordered_map>`中定义了类模板`unordered_map`。并满足 容器 概念，这意味着它支持`begin()`、`end()`、`size()`、`max_size()`、`empty()`、 `swap()`等方法。

`unordered_set`(C++11)｜`unordered_map`(C++11)｜`unordered_multiset`(C++11)｜`unordered_multimap`(C++11)｜描述

(constructor)｜ (constructor)｜ (constructor)｜ (constructor)｜构造函数包括缺省构造、拷贝构造、移动构造等

(destructor)｜ (destructor)｜ (destructor)｜ (destructor)｜析构函数

`[http://en.cppreference.com/w/cpp/container/unordered_set/operator= operator=]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/operator= operator=]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/operator= operator=]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/operator= operator=]`｜赋值运算符

`[http://en.cppreference.com/w/cpp/container/unordered_set/get_allocator get_allocator]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/get_allocator get_allocator]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/get_allocator get_allocator]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/get_allocator get_allocator]`｜返回分配器，用于给容器元素分配内存

Element access｜不适用｜`[http://en.cppreference.com/w/cpp/container/unordered_map/at at]`｜不适用｜不适用｜带边界检查的返回元素（C++11）

不适用｜ operator`[]`｜不适用｜不适用｜不带边界检查的返回元素，可用于插入元素

Iterators｜`[http://en.cppreference.com/w/cpp/container/unordered_set/begin begin,cbegin]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/begin begin,cbegin]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/begin begin,cbegin]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/begin begin,cbegin]`｜返回指向哈希表指定条目（bucket）所包含的首元素的迭代器 （C++11）

`[http://en.cppreference.com/w/cpp/container/unordered_set/end end]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/end end]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/end end]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/end end]`｜指向容器末尾的迭代器

Capacity｜`[http://en.cppreference.com/w/cpp/container/unordered_set/empty empty]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/empty empty]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/empty empty]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/empty empty]`｜检查容器是否为空

`[http://en.cppreference.com/w/cpp/container/unordered_set/size size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/size size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/size size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/size size]`｜返回容器元素的数量。

`[http://en.cppreference.com/w/cpp/container/unordered_set/max_size max_size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/max_size max_size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/max_size max_size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/max_size max_size]`｜返回受系统与库的实现所限，容器元素的最大可能数量

Modifiers｜`[http://en.cppreference.com/w/cpp/container/unordered_set/clear clear]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/clear clear]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/clear clear]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/clear clear]`｜清空容器

`[http://en.cppreference.com/w/cpp/container/unordered_set/insert insert]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/insert insert]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/insert insert]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/insert insert]`｜插入元素

`[http://en.cppreference.com/w/cpp/container/unordered_set/emplace emplace]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/emplace emplace]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/emplace emplace]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/emplace emplace]`｜原位构造 (C++11)

`[http://en.cppreference.com/w/cpp/container/unordered_set/emplace_hint emplace_hint]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/emplace_hint emplace_hint]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/emplace_hint emplace_hint]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/emplace_hint emplace_hint]`｜使用hint原位构造 (C++11)

`[http://en.cppreference.com/w/cpp/container/unordered_set/try_emplace try_emplace]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/try_emplace try_emplace]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/try_emplace try_emplace]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/try_emplace try_emplace]`｜如果给定的key在容器中不存在，原位构造一个元素 (C++17)

`[http://en.cppreference.com/w/cpp/container/unordered_set/erase erase]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/erase erase]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/erase erase]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/erase erase]`｜擦除元素

`[http://en.cppreference.com/w/cpp/container/unordered_set/swap swap]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/swap swap]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/swap swap]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/swap swap]`｜两个容器交换内容

Lookup｜`[http://en.cppreference.com/w/cpp/container/unordered_set/count count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/count count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/count count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/count count]`｜返回匹配指定键值的元素数量

`[http://en.cppreference.com/w/cpp/container/unordered_set/find find]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/find find]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/find find]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/find find]`｜发现具有指定键值的元素

`[http://en.cppreference.com/w/cpp/container/unordered_set/equal_range equal_range]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/equal_range equal_range]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/equal_range equal_range]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/equal_range equal_range]`｜返回匹配指定键值的元素范围

`[http://en.cppreference.com/w/cpp/container/unordered_set/reserve reserve]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/reserve reserve]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/reserve reserve]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/reserve reserve]`｜扩展容器的容量（C++11）

Bucket接口｜`[http://en.cppreference.com/w/cpp/container/unordered_set/bucket_size bucket_size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/bucket_size bucket_size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/bucket_size bucket_size]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/bucket_size bucket_size]`｜返回指定索引的哈希表条目所容纳的容器元素的数量（C++11）

哈希策略

`[http://en.cppreference.com/w/cpp/container/unordered_set/hash_function hash_function]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/hash_function hash_function]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/hash_function hash_function]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/hash_function hash_function]`｜返回用于创制键值hash的函数对象

`[http://en.cppreference.com/w/cpp/container/unordered_set/key_eq key_eq]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/key_eq key_eq]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/key_eq key_eq]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/key_eq key_eq]`｜返回键值比较函数对象（C++11）

`[http://en.cppreference.com/w/cpp/container/unordered_set/rehash rehash]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/rehash rehash]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/rehash rehash]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/rehash rehash]`｜设定哈希表的条目（bucket）数量并重新生成哈希表（C++11）

`[http://en.cppreference.com/w/cpp/container/unordered_set/max_load_factor max_load_factor]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/max_load_factor max_load_factor]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/max_load_factor max_load_factor]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/max_load_factor max_load_factor]`｜返回或者设置哈希表的每个条目能容纳的容器元素的最大数量（C++11）

`[http://en.cppreference.com/w/cpp/container/unordered_set/load_factor load_factor]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/load_factor load_factor]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/load_factor load_factor]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/load_factor load_factor]`｜返回哈希表的每个条目容纳的容器元素的平均数量（C++11）

`[http://en.cppreference.com/w/cpp/container/unordered_set/max_bucket_count max_bucket_count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/max_bucket_count max_bucket_count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/max_bucket_count max_bucket_count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/max_bucket_count max_bucket_count]`｜返回由于系统及库的实现所能支持的哈希表条目的最大可能数量（C++11）

`[http://en.cppreference.com/w/cpp/container/unordered_set/bucket_count bucket_count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/bucket_count bucket_count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/bucket_count bucket_count]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/bucket_count bucket_count]`｜返回容器中的哈希表条目的数量（C++11）

`[http://en.cppreference.com/w/cpp/container/unordered_set/bucket bucket]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/bucket bucket]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/bucket bucket]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/bucket bucket]`｜返回指定键值所匹配的哈希表条目的索引（C++11）

Observers｜`[http://en.cppreference.com/w/cpp/container/unordered_set/operator_cmp operator==,!=]`｜`[http://en.cppreference.com/w/cpp/container/unordered_map/operator_cmp operator==,!=]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multiset/operator_cmp operator==,!=]`｜`[http://en.cppreference.com/w/cpp/container/unordered_multimap/operator_cmp operator==,!=]`｜两个容器的内容是否相同

## 例子

```cpp
#include <iostream>
#include <string>
#include <unordered_map>
 
int main()
{
    std::unordered_map<std::string, int> months;
    months["january"] = 31;
    months["february"] = 28;
    months["march"] = 31;
    months["april"] = 30;
    months["may"] = 31;
    months["june"] = 30;
    months["july"] = 31;
    months["august"] = 31;
    months["september"] = 30;
    months["october"] = 31;
    months["november"] = 30;
    months["december"] = 31;
    std::cout << "september -> " << months["september"] << std::endl;
    std::cout << "april     -> " << months["april"] << std::endl;
    std::cout << "december  -> " << months["december"] << std::endl;
    std::cout << "february  -> " << months["february"] << std::endl;

    //判断map中是否包含一个键值，没有直接做此事的成员函数。类似其他的STL容器，解决办法是：
    if( months.find("no_value") == months.end() )
    {
          printf("No such key in the map.");
    }
    return 0;
}
```

## 定制哈希函数

定制的哈希函数的参数为到定制类型的const引用，返回类型为size_t

```cpp
struct X{int i,j,k;};

struct hash_X{
  size_t operator()(const X &x) const{
    return hash<int>()(x.i) ^ hash<int>()(x.j) ^ hash<int>()(x.k);
  }
};
```

定制哈希函数作为std::unordered_map的模板参数使用。

```cpp
 std::unordered_map<X,int,hash_X> my_map;
```

或者通过特化std::hash来使用。

```cpp
namespace std {
    template <>
        class hash<X>{
        public :
        size_t operator()(const X &x ) const{
            return hash<int>()(x.i) ^ hash<int>()(x.j) ^ hash<int>()(x.k);
        }
    };
}

//...
 std::unordered_map<X,int> my_map;
```