Map是STL[1]的一個關聯容器,它提供一對一(其中第一個能夠稱爲關鍵字,每一個關鍵字只能在map中出現一次,第二個可能稱爲該關鍵字的值)的數據處理能力,因爲這個特性,它完成有可能在咱們處理一對一數據的時候,在編程上提供快速通道。這裏說下map內部數據的組織,map內部自建一顆紅黑樹(一種非嚴格意義上的平衡二叉樹),這顆樹具備對數據自動排序的功能,因此在map內部全部的數據都是有序的,後邊咱們會見識到有序的好處。java
hash_map基於hash table(哈希表)。 哈希表最大的優勢,就是把數據的存儲和查找消耗的時間大大下降,幾乎能夠當作是常數時間;而代價僅僅是消耗比較多的內存。然而在當前可利用內存愈來愈多的狀況下,用空間換時間的作法是值得的。另外,編碼比較容易也是它的特色之一。ios
其基本原理是:使用一個下標範圍比較大的數組來存儲元素。能夠設計一個函數(哈希函數,也叫作散列函數),使得每一個元素的關鍵字都與一個函數值(即數組下標,hash值)相對應,因而用這個數組單元來存儲這個元素;也能夠簡單的理解爲,按照關鍵字爲每個元素「分類」,而後將這個元素存儲在相應「類」所對應的地方,稱爲桶。編程
可是,不可以保證每一個元素的關鍵字與函數值是一一對應的,所以極有可能出現對於不一樣的元素,卻計算出了相同的函數值,這樣就產生了「衝突」,換句話說,就是把不一樣的元素分在了相同的「類」之中。 總的來講,「直接定址」與「解決衝突」是哈希表的兩大特色。數組
hash_map,首先分配一大片內存,造成許多桶。是利用hash函數,對key進行映射到不一樣區域(桶)進行保存。其插入過程是:app
1.獲得key
2.經過hash函數獲得hash值
3.獲得桶號(通常都爲hash值對桶數求模)
4.存放key和value在桶內。
其取值過程是:
1.獲得key
2.經過hash函數獲得hash值
3.獲得桶號(通常都爲hash值對桶數求模)
4.比較桶的內部元素是否與key相等,若都不相等,則沒有找到。
5.取出相等的記錄的value。
hash_map中直接地址用hash函數生成,解決衝突,用比較函數解決。這裏能夠看出,若是每一個桶內部只有一個元素,那麼查找的時候只有一次比較。當許多桶內沒有值時,許多查詢就會更快了(指查不到的時候).less
因而可知,要實現哈希表, 和用戶相關的是:hash函數和比較函數。這兩個參數恰好是咱們在使用hash_map時須要指定的參數。 ide
Unordered maps are associative containers that store elements formed by the combination of a key value and amapped value, and which allows for fast retrieval of individual elements based on their keys.
In an unordered_map, the key value is generally used to uniquely identify the element, while the mapped value is an object with the content associated to this key. Types of key and mapped value may differ.
Internally, the elements in the unordered_map are not sorted in any particular order with respect to either theirkey or mapped values, but organized into buckets depending on their hash values to allow for fast access to individual elements directly by their key values (with a constant average time complexity on average).
unordered_map containers are faster than map containers to access individual elements by their key, although they are generally less efficient for range iteration through a subset of their elements.
Unordered maps implement the direct access operator (operator[]) which allows for direct access of themapped value using its key value as argument.
函數
boost::unordered_map, 它與 stl::map的區別就是,stl::map是按照operator<比較判斷元素是否相同,以及比較元素的大小,而後選擇合適的位置插入到樹中。因此,若是對map進行遍歷(中序遍歷)的話,輸出的結果是有序的。順序就是按照operator< 定義的大小排序。
而boost::unordered_map是計算元素的Hash值,根據Hash值判斷元素是否相同。因此,對unordered_map進行遍歷,結果是無序的。
用法的區別就是,stl::map 的key須要定義operator< 。 而boost::unordered_map須要定義hash_value函數而且重載operator==。對於內置類型,如string,這些都不用操心。對於自定義的類型作key,就須要本身重載operator< 或者hash_value()了。
最後,說,當不須要結果排好序時,最好用unordered_map。
其實,stl::map對於與java中的TreeMap,而boost::unordered_map對應於java中的HashMap。 測試
記錄數N=100000時,結果以下:this
Map類型 |
插入耗時,單位秒 |
插入加遍歷耗時,單位秒 |
內存佔用狀況 |
map |
0.110705 |
0.171859 |
5,780kB |
hash_map |
0.079074 |
0.091751 |
5,760kB |
unordered_map |
0.041311 |
0.050298 |
5,216kB |
記錄數N=1000000時,結果以下:
Map類型 |
插入耗時,單位秒 |
插入加遍歷耗時,單位秒 |
內存佔用狀況 |
map |
1.22678 |
1.95435 |
47,960kB |
hash_map |
0.684772 |
0.814646 |
44,632kB |
unordered_map |
0.311155 |
0.386898 |
40,604kB |
記錄數N=10000000時,結果以下:
Map類型 |
插入耗時,單位秒 |
插入加遍歷耗時,單位秒 |
內存佔用狀況 |
map |
14.9517 |
23.9928 |
469,844kB |
hash_map |
5.93318 |
7.18117 |
411,904kB |
unordered_map |
3.64201 |
4.43355 |
453,920kB |
記錄數N=100000000時,結果以下:
Map類型 |
插入耗時,單位秒 |
插入加遍歷耗時,單位秒 |
內存佔用狀況 |
map |
167.941 |
251.591 |
4,688,692kB |
hash_map |
46.3518 |
57.6972 |
3,912,632kB |
unordered_map |
28.359 |
35.122 |
4,3012,56kB |
運行效率方面:unordered_map最高,hash_map其次,而map效率最低
佔用內存方面:hash_map內存佔用最低,unordered_map其次,而map佔用最高
stl::map
output:
Tom1 20
Tom3 22
Tom4 23
Tom5 24
operator<的重載必定要定義成const。由於map內部實現時調用operator<的函數好像是const。
因爲operator<比較的只是age,因此由於Tom2和Tom3的age相同,因此最終結果裏面只有Tom3,沒有Tom2
boost::unordered_map
輸出
Tom1 20
Tom5 24
Tom4 23
Tom2 22
Tom3 22
必需要自定義operator==和hash_value。 重載operator==是由於,若是兩個元素的hash_value的值相同,並不能判定這兩個元素就相同,必須再調用operator==。 固然,若是hash_value的值不一樣,就不須要調用operator==了。