Qt容器(QMap/QHash 等)使用詳解
一、Qt容器的遍歷器
Qt 的容器類提供了兩種風格的遍歷器:Java 風格和 STL 風格。
每一種容器都有兩種 Java 風格的遍歷器:一種提供只讀訪問,一種提供讀寫訪問:
容器 |
只讀遍歷器 |
讀寫遍歷器 |
QList<T>,QQueue<T> |
QListIterator<T> |
QMutableListIterator<T> |
QLinkedList<T> |
QLinkedListIterator<T> |
QMutableLinkedListIterator<T> |
QVector<T>,QStack<T> |
QVectorIterator<T> |
QMutableVectorIterator<T> |
QSet<T> |
QSetIterator<T> |
QMutableSetIterator<Key,T> |
QMap<Key, T>,QMultiMap<Key, T> |
QMapIterator<Key,T> |
QMutableMapIterator<Key,T> |
QHash<Key, T>,QMultiHash<Key, T> |
QHashIterator<Key,T> |
QMutableHashIterator<Key,T> |
STL 風格的遍歷器
STL 風格的遍歷器從 Qt 2.0 就開始提供。這種遍歷器能夠相容 Qt 和 STL 的通用演算法,並且為速度進行了優化。同 Java 風格遍歷器類似,Qt 也提供了兩種 STL 風格的遍歷器:一種是隻讀訪問,一種是讀寫訪問。我們推薦儘可能使用只讀訪問,因為它們要比讀寫訪問的遍歷器快一些。
容器 |
只讀遍歷器 |
讀寫遍歷器 |
QList<T>,QQueue<T> |
QList<T>::const_iterator |
QList<T>::iterator |
QLinkedList<T> |
QLinkedList<T>::const_iterator |
QLinkedList<T>::iterator |
QVector<T>,QStack<T> |
QVector<T>::const_iterator |
QVector<T>::iterator |
QSet<T> |
QSet<T>::const_iterator |
QSet<T>::iterator |
QMap<Key, T>,QMultiMap<Key, T> |
QMap<Key, T>::const_iterator |
QMap<Key, T>::iterator |
QHash<Key, T>,QMultiHash<Key, T> |
QHash<Key, T>::const_iterator |
QHash<Key, T>::iter |
二、QMap和QHash的對比分析
QMap和QHash的介面相同,可直接替換使用,它們之間的差異如下:
(1)、QHash的查詢速度明顯快於QMap
(2)、QHash佔用的儲存空間明顯多於QMap
(3)、QHash以任意的方式儲存元素
(4)、QMap以Key順序儲存元素
(5)、QHash如果使用自定義型別作為主鍵,QHash的鍵型別必須提供operator == () 和 qHash(key)函式
(6)、QMap如果使用自定義型別作為主鍵,QMap的鍵型別必須提供operator <函式
三、使用例項
#include "mainwindow.h"
#include <QApplication>
#include <QMap>
#include <QHash>
#include <QDate>
#include <QDebug>
struct Student
{
QString name;
int no;
bool operator <(const struct Student& other) const
{
if (name < other.name)
{
return true;
}
else if (name == other.name)
{
return no < other.no;
}
return false;
}
};
class Employee
{
public:
Employee() {}
Employee(const QString &name, const QDate &dateOfBirth){myName = name;myDateOfBirth = dateOfBirth;}
const QString name(){return myName;}
const QDate dateOfBirth(){return myDateOfBirth;}
inline bool operator==(const Employee &other) const
{
return (myName==other.myName && myDateOfBirth==other.myDateOfBirth);
}
//以下的寫法是錯誤的//error: passing 'const Employee' as 'this' argument of 'const QString Employee::name()' discards qualifiers
/*inline bool operator==(const Employee &other) const
{
return myName == other.name()
&& myDateOfBirth == other.dateOfBirth();
}*/
public:
QString myName;
QDate myDateOfBirth;
};
//以下的寫法是錯誤的://error: passing 'const Employee' as 'this' argument of 'const QString Employee::name()' discards qualifiers
/*inline uint qHash(const Employee &key)
{
return qHash(key.name()) ^ key.dateOfBirth().day();
}*/
inline uint qHash(const Employee key)
{
//^ -----按位異或(Xor)是一種可逆運算子,只有在兩個比較的位不同時其結果是1,否則結果為0。
return qHash(key.myName) ^ key.myDateOfBirth.day();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//----------------Java 風格的遍歷器
/*每一種容器都有兩種 Java 風格的遍歷器:一種提供只讀訪問,一種提供讀寫訪問:
容器 只讀遍歷器 讀寫遍歷器
QList<T>,QQueue<T> QListIterator<T> QMutableListIterator<T>
QLinkedList<T> QLinkedListIterator<T> QMutableLinkedListIterator<T>
QVector<T>,QStack<T> QVectorIterator<T> QMutableVectorIterator<T>
QSet<T> QSetIterator<T> QMutableSetIterator<T>
QMap<Key, T>,QMultiMap<Key, T> QMapIterator<T> QMutableMapIterator<T>
QHash<Key, T>,QMultiHash<Key, T> QHashIterator<T> QMutableHashIterator<T>
*/
//----------------end Java 風格的遍歷器
//------QMap
QMap<int,QString> id2NameMap;
id2NameMap.insert(2,"name2");
id2NameMap.insert(1,"name1");
id2NameMap.insert(3,"name3");
qDebug()<<id2NameMap;
//只讀遍歷器
QMapIterator<int,QString> it1(id2NameMap);
while (it1.hasNext())
{
it1.next();
if(2 == it1.key())
{
qDebug() << it1.value();
}
}
//讀寫遍歷器
QMutableMapIterator<int,QString> mit1(id2NameMap);
while (mit1.hasNext())
{
mit1.next();
if(2 == mit1.key())
{
mit1.setValue("name2new");
qDebug() << mit1.value();
}
}
qDebug()<<id2NameMap;
//------end QMap
//----------------STL 風格的遍歷器
/*STL 風格的遍歷器從 Qt 2.0 就開始提供。這種遍歷器能夠相容 Qt 和 STL 的通用演算法,並且為速度進行了優化。
* 同 Java 風格遍歷器類似,Qt 也提供了兩種 STL 風格的遍歷器:一種是隻讀訪問,一種是讀寫訪問。
* 我們推薦儘可能使用只讀訪問,因為它們要比讀寫訪問的遍歷器快一些。
容器 只讀遍歷器 讀寫遍歷器
QList<T>,QQueue<T> QList<T>::const_iterator QList<T>::iterator
QLinkedList<T> QLinkedList<T>::const_iterator QLinkedList<T>::iterator
QVector<T>,QStack<T> QVector<T>::const_iterator QVector<T>::iterator
QSet<T> QSet<T>::const_iterator QSet<T>::iterator
QMap<Key, T>,QMultiMap<Key, T> QMap<Key, T>::const_iterator QMap<Key, T>::iterator
QHash<Key, T>,QMultiHash<Key, T> QHash<Key, T>::const_iterator QHash<Key, T>::iter
*/
//------QHash
QHash<int,QString> id2NameHash;
id2NameHash.insert(2,"hashName2");
id2NameHash.insert(1,"hashName1");
id2NameHash.insert(3,"hashName3");
qDebug()<<id2NameHash;
//只讀遍歷器
QHash<int,QString>::const_iterator rIt1;
for (rIt1 = id2NameHash.begin(); rIt1 != id2NameHash.end(); ++rIt1)
{
if(2 == rIt1.key())
{
qDebug() << rIt1.value();
}
}
//讀寫遍歷器
QHash<int,QString>::iterator wIt1;
for (wIt1 = id2NameHash.begin(); wIt1 != id2NameHash.end(); ++wIt1)
{
if(2 == wIt1.key())
{
//修改內容
*wIt1 = "hashName2new";// 使用 * 運算子獲取遍歷器所指的元素
qDebug() << wIt1.value();
}
else if(3 == wIt1.key())
{
//修改內容
id2NameHash.insert(3,"hashName3new");
qDebug() << wIt1.value();
}
}
qDebug()<<id2NameHash;
//------end QHash
//----------------------自定義key型別
//QHash的鍵型別必須提供operator == () 和 qHash(key)函式
//QMap的鍵型別必須提供operator <
//------自定義 QMap的Key型別
QMap<Student,QString> key2NameMap;
Student tmp;
tmp.no = 2;
tmp.name = "name2";
key2NameMap.insert(tmp,"name2");
tmp.no = 1;
tmp.name = "name1";
key2NameMap.insert(tmp,"name1");
tmp.no = 3;
tmp.name = "name3";
key2NameMap.insert(tmp,"name3");
// qDebug()<<key2NameMap;
Student find;
find.no = 2;
find.name = "name2";
QMap<Student,QString>::iterator cusIt1 = key2NameMap.find(find);
if(cusIt1 != key2NameMap.end())
{
qDebug()<<"I can find";
}
else
{
qDebug()<<"I can not find";
}
//------end 自定義 QMap的Key型別
//------自定義 QHash的Key型別
QHash<Employee,QString> customHash;
customHash.insert(Employee("name1", QDate(2018,10,21)),"name1");
customHash.insert(Employee("name3", QDate(2018,10,23)),"name3");
customHash.insert(Employee("name2", QDate(2018,10,22)),"name2");
customHash.insert(Employee("name7", QDate(2018,10,27)),"name7");
//只讀遍歷器
QHash<Employee,QString>::const_iterator rIt2;
for (rIt2 = customHash.begin(); rIt2 != customHash.end(); ++rIt2)
{
qDebug() << rIt2.key().myName << ":" << rIt2.value();
}
//------end 自定義 QHash的Key型別
MainWindow w;
w.show();
return a.exec();
}