Qt扫盲-QMap理论总结
QMap 是Qt的通用容器类之一。它存储(键,值) 对,并提供与键相关联的值的快速查找。其实就是一个键值对的集合,经常使用的。具体更详细还得看看帮助文档QMap和QHash提供了非常相似的功能。QHash提供了比QMap更快的平均查找速度。在遍历QHash时,元素的顺序是任意的。在QMap中,元素总是按键排序了的。QHash的键类型必须提供==() 运算符和一个全局的QHash (key) 函数。
一、概述
QMap 是Qt的通用容器类之一。它存储(键,值) 对,并提供与键相关联的值的快速查找。其实就是一个键值对的集合,经常使用的。具体更详细还得看看帮助文档
QMap和QHash提供了非常相似的功能。区别在于:
- QHash提供了比QMap更快的平均查找速度。
- 在遍历QHash时,元素的顺序是任意的。在QMap中,元素总是按键排序了的。
- QHash的键类型必须提供==() 运算符和一个全局的QHash (key) 函数。QMap的键类型必须提供<运算符来指定总顺序。由于Qt 5.8.1,使用指针类型作为键也是安全的,即使底层运算符<() 没有提供总的顺序。
二、使用
1. 初始化及属性
下面是一个QMap的例子,键为QString,值为int:
QMap<QString, int> map;
常用的函数:
- size() :Map的大小
- empty():是不是空
- key():这个第一个元素的键
- keys():返回所有的键
- values():返回所有的值
2. 插入元素
map["one"] = 1;
map["three"] = 3;
map["seven"] = 7;
这会将以下3个键值对插入到QMap中:(“one”, 1) 、(“three”, 3) 和(“seven”, 7) 。
另一种向map中插入元素的方法是使用insert() :
map.insert("twelve", 12) ;
通常,QMap每个键只允许一个值。如果使用QMap中已经存在的键调用insert() ,之前的值将被删除。例如:
map.insert("plenty", 100) ;
map.insert("plenty", 2000) ;
// map.value("plenty") == 2000
我们也可以使用insertMulti() 而不是insert() 来为每个键存储多个值(或者使用便捷的子类QMultiMap) 。如果想取得一个键对应的所有值,可以使用values(const key &key) ,它会返回一个QList:
QList<int> values = map.values("plenty") ;
for (int i = 0; i < values.size() ; ++i)
cout << values.at(i) << Qt::endl;
共享相同键的项可以从最近插入到最近插入。另一种方法是调用find() 来获取第一个键对应的stl风格的迭代器,也就是说find() 返回的也是一个可迭代的对象,我们可以从那里开始迭代:
QMap<QString, int>::iterator i = map.find("plenty") ;
while (i != map.end() && i.key() == "plenty") {
cout << i.value() << Qt::endl;
++i;
}
3. 查找值,获取值
要查找一个值,可以使用operator 或value() :
int num1 = map["thirteen"];
int num2 = map.value("thirteen") ;
如果在map中没有指定键的项,这些函数返回一个默认构造的值。就是这个键的构造函数,然后像int、double之类的就是0,QString 就是空字符串。
如果你想检查map中是否包含某个键,可以使用contains() :
int timeout = 30;
if (map.contains("TIMEOUT") )
timeout = map.value("TIMEOUT") ;
还有一个value() 重载方法,如果指定的键不存在,则使用第二个参数作为默认值:
int timeout = map.value("TIMEOUT", 30) ;
一般来说,我们推荐使用contains() 和value() 而不是 [ ] 在map中查找键。因为如果map中不存在键相同的元素,[ ]会静默地将元素插入到 map 中(除非map是const) 。有时候就要非常注意这个问题。例如,下面的代码片段将在内存中创建1000个元素:
// WRONG
QMap<int, QWidget *> map;
...
for (int i = 0; i < 1000; ++i) {
if (map[i] == okButton)
cout << "Found button at index " << i << Qt::endl;
}
为了避免这个问题,将上面代码中的map[i]替换为map.value(i) 。
4. 遍历键值对
如果想遍历存储在QMap中的所有键值对,可以使用迭代器。QMap提供了java风格的迭代器(QMapIterator和QMutableMapIterator) 和stl风格的迭代器(QMap::const_iterator和QMap::iterator) 。
下面是如何使用java风格的迭代器迭代QMap<QString, int>:
QMapIterator<QString, int> i(map) ;
while (i.hasNext() ) {
i.next() ;
cout << i.key() << ": " << i.value() << Qt::endl;
}
下面是相同的代码,但这次使用了stl风格的迭代器:
QMap<QString, int>::const_iterator i = map.constBegin() ;
while (i != map.constEnd() ) {
cout << i.key() << ": " << i.value() << Qt::endl;
++i;
}
每一个键值对 都是 按键升序遍历。
如果你只需要从map中提取值(而不是键) ,你也可以使用foreach:
QMap<QString, int> map;
...
foreach (int value, map)
cout << value << Qt::endl;
5. 删除元素
有几种方法可以从QMap中删除元素。
一种方法是调用remove() 方法;这将删除具有给定键的任何项。
另一种方法是使用QMutableMapIterator::remove() 。
此外,你可以使用clear() 清除整个QMap。
6. 注意
QMap的键和值数据类型必须是可分配的数据类型。这涵盖了您可能遇到的大多数数据类型,但是编译器不允许您将QWidget存储为值;相反,存储一个QWidget *。此外,QMap的键类型必须提供<运算符。QMap使用它来排序元素,如果x < y和y < x都不为真,则假设两个键x和y相等。
例子:
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
class Employee
{
public:
Employee() {}
Employee(const QString &name, QDate dateOfBirth) ;
...
private:
QString myName;
QDate myDateOfBirth;
};
inline bool operator<(const Employee &e1, const Employee &e2)
{
if (e1.name() != e2.name() )
return e1.name() < e2.name() ;
return e1.dateOfBirth() < e2.dateOfBirth() ;
}
#endif // EMPLOYEE_H
在这个例子中,我们首先比较员工的名字。如果他们相等,我们比较他们的出生日期来打破平局。
更多推荐
所有评论(0)