首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Qt 學習之路 (37):關聯式容器 QMap 與 QHash 深度解析

     編輯:關於C語言

Qt 容器類別中,關聯式容器 儲存的是鍵值對,對應數學上的映射關係。Qt 提供兩大核心實作:QMap<K, T>(有序、跳表實作)與 QHash<K, T>(無序、雜湊表實作)。本文系統整理其用法、效能特性與遍歷技巧。

核心概念:從陣列到關聯容器

陣列可視為 <int, Object> 的特殊關聯容器(鍵固定為整數索引)。將鍵型別擴展為任意型別,即得關聯容器。典型資料結構為雜湊表。

QMap<K, T>:有序映射

  • 底層採用 跳表 實作,依鍵 升序 儲存。
  • 鍵型別 K 必須支援 operator< 比較。
  • 適用於需要有序遍歷、範圍查詢的場景。

基本操作

QMap<QString, int> map;

// 插入
map.insert("eins", 1);
map.insert("sieben", 7);
map.insert("dreiundzwanzig", 23);

// 運算子 [] 寫法(同陣列)
map["eins"] = 1;
map["sieben"] = 7;

// 讀取:[] 若鍵不存在會自動插入預設值
int val = map["eins"];          // 存在 → 回傳值
int val2 = map["nonexist"];     // 不存在 → 插入 0 並回傳 0

// 安全讀取:value() 不會插入新鍵
int val3 = map.value("dreiundzwanzig");      // 不存在 → 回傳 0
int val4 = map.value("delay", 30);           // 不存在 → 回傳預設值 30

// 判斷鍵是否存在
if (map.contains("delay")) { /* ... */ }

// 取得所有鍵/值(回傳 QList)
QList<QString> keys = map.keys();
QList<int>     vals = map.values();

多值映射:QMultiMap

單一鍵對應多個值時使用 QMultiMap<K, T>:

QMultiMap<int, QString> multiMap;
multiMap.insert(1, "one");
multiMap.insert(1, "eins");
multiMap.insert(1, "uno");

QList<QString> vals = multiMap.values(1); // 取得鍵 1 的所有值

QHash<K, T>:高效雜湊映射

  • 底層為 雜湊表,查找速度 遠快於 QMap(平均 O(1))。
  • 儲存順序 不保證(無序)。
  • 鍵型別 K 需支援 operator== 並提供全域 qHash(K) 函式。Qt 已內建支援 int、指標、QChar、QString、QByteArray。
  • API 與 QMap 几乎相同,可無縫切換。

容量控制

QHash<QString, int> hash;
hash.reserve(10000);  // 預分配桶數,減少 rehash
// 大量插入...
hash.squeeze();       // 縮減至最小足夠容量

多值與衍生容器

  • QMultiHash<K, T>:單鍵多值版本。
  • QCache<K, T>:LRU 快取容器。
  • QSet<K>:僅儲存鍵的集合(底層同 QHash)。

遍歷關聯容器的三種風格

1. Java 風格迭代器(推薦:可同時取得鍵值)

QMap<QString, int> map;
// ...填入資料...

int sum = 0;
QMapIterator<QString, int> it(map);
while (it.hasNext()) {
    sum += it.next().value(); // next() 回傳 QPair<Key, Value>
}

// 需要分別存取鍵/值
QMapIterator<QString, int> it2(map);
while (it2.hasNext()) {
    it2.next();
    if (it2.value() > maxVal) {
        maxKey = it2.key();
        maxVal = it2.value();
    }
}

// 可修改值的 Mutable 迭代器
QMutableMapIterator<QString, int> mit(map);
while (mit.hasNext()) {
    mit.next();
    if (mit.value() < 0)
        mit.setValue(-mit.value());
}

2. STL 風格迭代器

for (QMap<QString, int>::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) {
    cout << it.key() << ": " << it.value() << endl;
}

3. foreach 迴圈(需分別迭代鍵與值)

QMultiMap<QString, int> multiMap;
// ...
foreach (const QString &key, multiMap.keys()) {
    foreach (int value, multiMap.values(key)) {
        doSomething(key, value);
    }
}

選擇建議

需求推薦容器
需有序遍歷、範圍查詢QMap
純查找/插入/刪除,追求極致速度QHash
單鍵多值 + 有序QMultiMap
單鍵多值 + 高速QMultiHash
LRU 快取QCache
單純集合QSet

小結

掌握 QMap 與 QHash 的特性差異、鍵型別需求、多值變體與遍歷技巧,能讓 Qt 程式在資料結構選型上更精準、效能更優。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved