容器對比說明圖
廢話不多說,先上圖。no picture say jb..

容器對比說明圖.png
前言
日常工作中常用的std容器一般vector、list、queue、map,對于multimap此類很少用到。(主要沒有遇到合適的場景,可能我太菜)
嘗試使用
multimap與unordered_multimap常用于'多對多'場景下,那么什么樣的多對多呢,我百度了一圈也沒見有人舉例。根據(jù)multimap的主要特性,“key可以重復(fù)”我們來舉個(gè)簡單點(diǎn)的栗子,比如我們需要將一個(gè)年級的學(xué)生都存到一個(gè)multimap中,大概就會(huì)是以下這個(gè)樣子。
假設(shè)我們有這樣的一個(gè)結(jié)構(gòu):
typedef struct {
int mID_;
int mAge_;
string mName_;
}StudentInfo;
假設(shè)這個(gè)年級有三個(gè)班,那數(shù)據(jù)可能以下面的這個(gè)樣子:
/*引入頭文件*/
#include<unordered_map>
/*定義學(xué)生*/
StudentInfo studentA = { 50, 16, "NameA" };
StudentInfo studentB = { 100, 17, "NameB" };
StudentInfo studentC = { 150, 16, "NameC" };
/*定義multimap,類型名字太長,使用別名*/
using StudentMultiMap = std::unordered_multimap<string/*班級*/, StudentInfo/*學(xué)生信息*/>;
StudentMultiMap allStudent;
/*對學(xué)生進(jìn)行存儲*/
//如果使用key無重復(fù)的則如此
allStudent.insert(std::make_pair("一班", studentA));
allStudent.insert(std::make_pair("二班", studentB));
allStudent.insert(std::make_pair("三班", studentC));
//如果key有重復(fù),實(shí)際情況下,每個(gè)班有多個(gè)同學(xué)
allStudent.insert(std::make_pair("一班", studentD));
allStudent.insert(std::make_pair("一班", studentE));
allStudent.insert(std::make_pair("一班", studentF));
multimap和unordered_multimap常用函數(shù)
//insert 插入一個(gè)對象
allStudent.insert(std::make_pair("一班", studentG));
//size 返回multimap中的對象個(gè)數(shù)
allStudent.size();
//empty 判斷是否為空
allStudent.empty();
//count 統(tǒng)計(jì)某個(gè)key的對象個(gè)數(shù)
allStudent.count("一班");
//find根據(jù)key查找對象,返回遍歷到的第一個(gè)使用該key迭代器
StudentMultiMap::iterator tmp = allStudent.find("二班");
//contains c++20才開始支持
allStudent.contains("三班"); //返回bool值,判斷是否擁有使用該key的對象
以下這兩個(gè)函數(shù)unordered_multimap是沒有的?。?!
單獨(dú)說明一下,對key進(jìn)行hash以后,在multimap中key的順序可能是:
一班(0),一班(1),二班(2),二班(3),三班(4),三班(5),//這是只是為了形象展示
如果對一班進(jìn)行l(wèi)ower_bound,那lower的iterator指向:0,而upper則指向:2
//lower_bound 返回指向首個(gè)不小于給定鍵的元素的迭代器
StudentMultiMap::iterator lower = allStudent.lower_bound("一班");
//upper_bound 返回指向首個(gè)大于給定鍵的元素的迭代器
StudentMultiMap::iterator upper = allStudent.upper_bound("一班");
//erase刪除指定key,或刪除某一個(gè)迭代器
allStudent.erase(tmp);//刪除tmp迭代器所指像的對象-單個(gè)
allStudent.erase("二班");//刪除所有key為'二班'的對象-多個(gè)
allStudent.erase(lower, upper);//刪除lower~upper這個(gè)區(qū)間-范圍
//equal_range 返回一個(gè)由lower和upper組成的pair
std::pair<StudentMultiMap::iterator, StudentMultiMap::iterator> stuRange = allStudent.equal_range("一班");
for (auto& it = stuRange.first; it != stuRange.second; it++) {
std::cout << it->second.mID_ << ":" << it->second.mAge_ << ":" << it->second.mName_ << std::endl;
}
//幾個(gè)迭代器,就不單獨(dú)說明了
begin
end
cbegin
cend
//清空multimap
clear
幾種對multimap遍歷的方式
1、auto臨時(shí)變量
for (const auto& tmp : allStudent) {
std::cout << tmp.second.mID_ << ":" << tmp.second.mAge_ << ":" << tmp.second.mName_ << std::endl;
}
2、原始for
const auto& end = allStudent.end();
for (StudentMultiMap::iterator tmp = allStudent.begin(); tmp != end ; tmp++) {
std::cout << tmp->second.mID_ << ":" << tmp->second.mAge_ << ":" << tmp->second.mName_ << std::endl;
}
回到使用場景
這種'多對多'的場景,使用multimap還是很好的。
1、像需要對流量進(jìn)行解析時(shí),需要對一個(gè)session所有包都關(guān)聯(lián)起來的時(shí)候,使用IP五元組做為key每個(gè)包做value
2、像對用戶的好友列表?
3、像用戶的購物車?
4、像配置文件?
等等等等吧,反正。。