關(guān)聯(lián)容器
可以保存任意多個具有相同類型的項衅谷,且它們由一個鍵索引。Qt提供兩個主要的關(guān)聯(lián)容器類:QMap<K, T>
和QHash<K, T>
似将。
QMap<K, T>
是一個以升序鍵順序存儲鍵值對的數(shù)據(jù)結(jié)構(gòu)。這種排列使它可以提供良好的查找插入性能及鍵序的迭代蚀苛。在內(nèi)部在验,QMap<K, T>
是作為一個跳越列表(skip-list)來實現(xiàn)執(zhí)行的。
在映射中插入項的一種簡單方式是調(diào)用insert()
:
QMap<QString, int> map;
map.insert("eins", 1);
map.insert("sieben", 7);
map.insert("dreiundzwanzig", 23);
另外堵未,也可以像下面一樣腋舌,給一個指定的鍵賦值:
map["eins"] = 1;
map["sieben"] = 7;
map["dreiundzwanzig"] = 23;
[]
操作符即可以用于插入也可以用于檢索。如果在非常量映射中使用[]為一個不存在的鍵檢索值渗蟹,則會用給定的鍵和空值創(chuàng)建一個新的項块饺。為了避免意外的創(chuàng)建空值赞辩,可以使用value()函數(shù)代替[]操作符來獲得項。
int val = map.value("dreiundzwanzig")
如果鍵不存在授艰,則利用值類型的默認構(gòu)造函數(shù)辨嗽,將返回一個默認值,同時不會創(chuàng)建新的項淮腾。對于基本類型和指針類型糟需,將返回0值。我們可以指定另一默認值作為value()
的第二個參數(shù)谷朝,例如:
int seconds = map.value("delay", 30);
這相當于:
int seconds = 30;
if (map.contains("delay");
seconds = map.value("delay");
QMap<K, T>的K和T數(shù)據(jù)類型可以是與int洲押、double、指針類型圆凰、有默認構(gòu)造函數(shù)的類杈帐、復(fù)制構(gòu)造函數(shù)和賦值操作符相似的基本數(shù)據(jù)類型。此外专钉,K類型必須提供operator<()
挑童,因為QMap<K, T>要使用這個操作符以提升鍵序順序存儲項。
QMap<K, T>的K和T有一對方便的函數(shù)keys()和values()驶沼,它們在處理小數(shù)據(jù)集時顯的特別有用炮沐。它們分別返回映射鍵的QList
和映射值的QList。
映射通常都是單一值的:如果賦予一個現(xiàn)有的鍵一個新值回怜,則原有的舊值將被該新值取代大年,以確保兩個項不會共有同一個鍵。通過使用insertMulti()函數(shù)或者QMlltiMap<K, T>方便的子類玉雾,可以讓多個鍵值對有相同的鍵翔试。QMap<K, T>重載了value(const K &), 返回一個給定鍵多有值的QList列表。例如:
QMultiMap<int, QString> multiMap;
multiMap.insert(1, "one");
multiMap.insert(1, "eins");
multiMap.insert(1, "uno");
QList<QString> vals = multiMap.values(1);
QHash<K, T>
是一個在哈希表中存儲鍵值對的數(shù)據(jù)結(jié)構(gòu)复旬。它的接口幾乎與QMap<K, T>相同垦缅,但是與QMap<K, T>相比,它對K的模板類型有不同的要求驹碍,而且它提供了比QMap<K, T>更快查找功能
壁涎。
除了對存儲在容器類中的所有值類型的一般要求,QHash<K, T>中K的值類型還需要提供一個operator==()
志秃,并需要一個能夠為鍵返回哈希值的全局qHash()函數(shù)的支持怔球。Qt已經(jīng)為qHash()函數(shù)提供了對整型、指針型浮还、QChar竟坛、QString以及QByteArray。
QHash<K, T>為它內(nèi)部的哈希表自動分配最初的存儲區(qū)域,并在有項被插入或者刪除時重新劃分所分配的存儲區(qū)域的大小担汤。也可以通過調(diào)用reserve()
或者squeeze()
來指定或者壓縮希望存儲到哈希表中的項的數(shù)目涎跨,以進行性能調(diào)整。通常的做法是利用我們預(yù)期的最大的項的數(shù)目來條用reserve(),然后插入數(shù)據(jù)崭歧,最后如果有多出的項隅很,則調(diào)用squeeze()以使內(nèi)存的使用減到最小。
雖然哈希表通常都是單一值的驾荣,但是使用insertMulti()函數(shù)或者MultiHash<K, T>方便的子類外构,也可以將多個值賦給同一個鍵。
除了QHash<K, T>之外播掷,Qt還提供了一個用來高速緩存與鍵相關(guān)聯(lián)的對象的QCache<K, T>類以及僅僅存儲鍵的QSet<K>容器审编。在內(nèi)部,它們都依賴于QHash<K, T>歧匈,且都像QHash<K, T>一樣對K的類型有相同的要求垒酬。
最簡便的遍歷存儲在關(guān)聯(lián)容器中多有鍵值對的方式是使用Java風(fēng)格的迭代器。因為迭代器必須能同時訪問鍵和值件炉,針對關(guān)聯(lián)容器的Java風(fēng)格的迭代器與連續(xù)容器的在運作方式有些差異勘究。只要區(qū)別在于next()和previous()函數(shù)返回一個代表鍵值對的對象,而不是一個簡單的值斟冕。我們可以使用key()和value()分別從這個對象中獲得鍵和值口糕。例如:
QMap<QString, int> map;
...
int sum = 0;
QMapIterator<QString, int> i(map);
while (i.hasNext())
sum += i.next().value();
如果需要同時存取鍵和值磕蛇,可以先忽略next()或previous()的返回值并使用迭代器的key()和value()函數(shù)景描,它們都是針對最后被跳過的項進行操作的:
QMapIterator<QString, int> i(map);
while(i.hasNext()){
i.next();
if (i.value() > largestValue){
largestKey = i.key();
largestValue = i.value();
}
}
QHash具有和QMap幾乎完全一樣的API,此類維護著一張哈希表秀撇,表的大小和數(shù)據(jù)項是自適應(yīng)的超棺,QHash是任意的順序住址他的數(shù)據(jù),當然他也支持一鍵多值(QMultiHash)QMap則是按順序入住他的數(shù)據(jù)呵燕。
兩者之間的區(qū)別是:
- QHash查找速度上顯著于QMap
- QHash以任意的方式進行存儲棠绘,而QMap則是以key順序進行存儲
- QHash的鍵類型必須提供operator==()和一個全局的QHash(key)函數(shù)。而QMap的鍵類型key必須提供operator<()函數(shù)
- 他們同樣具有兩種風(fēng)格的迭代容器iterator再扭,用來遍歷(Java遍歷氧苍,STL遍歷,QMutableIterator)
Java 迭代器遍歷(Java-style-iterator)
QMapIterator<QString,int> i(map);
while (i.hasNext()) {
i.next();
cout << i.key() << ": " << i.value() << endl;
}
STL迭代器遍歷(STL-style iterator)
QMap<QString,int>::const_iterator i = map.constBegin();
while (i != map.constEnd()) {
cout << i.key() << ": " << i.value() << endl;
++i;
}
QStringList
const QStringList CForceForm::c_lstRankName = QStringList() \
<< QStringLiteral("軍") << QStringLiteral("師") \
<< QStringLiteral("旅") << QStringLiteral("團") \
<< QStringLiteral("營") << QStringLiteral("連") \
<< QStringLiteral("排") << QStringLiteral("班") \
<< QStringLiteral("聯(lián)隊") << QStringLiteral("大隊") \
<< QStringLiteral("中隊") << QStringLiteral("小隊") \
<< QStringLiteral("組");
m_formRank = c_lstRankName[5]; //"連";