Qt容器(QMap/QHash 等)使用详解
一、Qt容器的遍历器Qt 的容器类提供了两种风格的遍历器:Java 风格和 STL 风格。每一种容器都有两种 Java 风格的遍历器:一种提供只读访问,一种提供读写访问:容器只读遍历器读写遍历器QList<T>,QQueue<T>QListIterator<...
一、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();
}
更多推荐
所有评论(0)