1. 容器类概述
Qt提供了多个基于模板的容器类,Qt的容器类比标准模板库(STL)中的容器类更轻巧、安全、易于使用。这些容器类是隐式共享和可重入的,它们进行了速度和存储优化,因此可以减少可执行文件的大小。此外,它们还是线程安全的,也就是说它们作为只读容器时可被多个线程访问。
Qt的容器类分为顺序容器(sequential containers)和关联容器(associative containers)。
容器迭代类用于遍历容器里的数据项,有Java类型的迭代类和STL类型的迭代类。Java类型的迭代类易于使用,提高高级功能,而STL类型的迭代类效率更高一些。
2. 顺序容器类
Qt的顺序容器类有 QList、QLinkedList、QVector、QStack 和QQueue。
2.1 QList
QList是最常用的容器类,虽然它是以数组列表(array-list)的形式实现的,但是在其前或后添加数据非常快,QList以下标索引的方式对数据项进行访问。
QList用于添加、插入、替换、移动、删除数据项的函数有:insert()、replace()、removeAt()、move()、swap()、append()、prepend()、removeFirst()和 removeLast()等。
QList提供下标索引方式访问数据项,如同数组一样,也提供at()函数,例如:
QList<QString> list;
list << "one" <<"two" <"three";
QString str1=list[1]); //str1=="two"
QString str0=list.at(0); //str0=="one"
QList的isEmpty()函数在数据项为空时返回 true,size()函数返回数据项的个数。
QList 是Qt 中最常用的容器类,很多函数的参数传递都是采用 QList 容器类,例如QAudioDeviceInfo的静态函数 availableDevices()的函数原型是:
QList<QAudioDeviceInfo> QAudioDeviceinfo::availableevices(QAudio::Mode mode)
其返回数据就是QAudioDeviceInfo 类型的QList列表。
2.2 QLinkedList
QLinkedList<T>是链式列表(linked-list),数据项不是用连续的内存存储的,它基于迭代器访问数据项,并且插入和删除数据项的操作时间相同。
除了不提供基于下标索引的数据项访问外,QLinkedList的其他接口函数与QList基本相同。
2.3 QVector
QVector<T>提供动态数组的功能,以下标索引访问数据。
QVector 的函数接口与 QList 几乎完全相同,QVector<T>的性能比 QList<T>更高,因为
QVector<T>的数据项是连续存储的。
2.4 QStack
QStack<T>是提供类似堆栈的后入先出(LIFO)操作的容器类,push()和 pop()是主要的接口函数。例如:
QStack<int> stack:
stack.push(10);
stack.push(20);
stack.push(30);
while (!stack.isEmpty())
cout << stack.pop() << endl;
******程序会依次输出30,20,10。*******
2.5 QQueue
QQueue<T>是提供类似于队列先入先出(FIFO)操作的容器类。enqueue()和 dequeue()是主要操作函数。例如:
QQueue<int> queue;
queue.enqueue(10);
queue.enqueue(20);
queue.enqueue(30);
while (!queue.isEmpty())
cout << queue.dequeue() << end1;
******程序会依次输出10,20,30。*******
3. 关联容器类
Qt提供关联容器类QMap、QMultiMap、QHash、QMultiHash和 QSet。
QMultiMap 和QMultiHash支持一个键关联多个值,QHash和QMultiHash类使用散列(Hash)函数进行查找,查找速度更快。
3.1 QSet
QSet 是基于散列表的集合模板类,它存储数据的顺序是不定的,查找值的速度非常快。
QSet<T>内部就是用QHash实现的。
定义QSet<T>容器和输入数据的实例代码如下:
QSet<QString> set;
set <<"dog" << "cat" << "tiger";
测试一个值是否包含于这个集合,用contains()函数,示例如下:
if (!set.contains("cat"))
...
3.2 QMap
QMap<Key,T>提供一个字典(关联数组),一个键映射到一个值。QMap 存储数据是按照键的顺序,如果不在乎存储顺序,使用QHash会更快。
定义QMap<QString,int>类型变量和赋值的示例代码如下:
QMap<QString,int> map;
map["one"]=1;
map["two"]=2;
map["three"]=3;
也可以使用insert()函数赋值,或remove()移除一个键值对,示例如下:
map.insert("four", 4);
map.remove("two");
要查找一个值,使用运算符“[]”或value()函数,示例如下:
int numl = map["one"];
int num2 = map.value("two");
如果在映射表中没有找到指定的键,会返回一个缺省构造值(default-constructed values),例如,如果值的类型是字符串,会返回一个空的字符串。
在使用value()函数查找键值时,还可以指定一个缺省的返回值,示例如下:
timeout = map.value("TIMEOUT",30);
这表示如果在map里找到键“TIMEOUT”,就返回关联的值,否则返回值为30。
3.3 QMultiMap
QMultiMap是QMap的子类,是用于处理多值映射的便利类。
多值映射就是一个键可以对应多个值。QMap 正常情况下不允许多值映射,除非使用
QMap::insertMulti() 添加键值对。
QMultiMap 是QMap的子类,所以QMap的大多数函数在QMultiMap都是可用的,但是有几个特殊的,QMultiMap::insert() 等效于 QMap::insertMulti() ,QMultiMap::replace() 等效于QMap::insert() 。
QMultiMap 使用示例如下:
QMultiMap<QString, int> mapl, map2, map3;
map1.insert("plenty", 100);
map1.insert("plenty",2000); // map1.size() == 2
map2.insert("plenty",5000); // map2.size() == 1
map3 = mapl + map2; // map3.size() == 3
QMultiMap 不提供“[]”操作符,使用value()函数访问最新插入的键的单个值。如果要获取
一个键对应的所有值,使用values()函数,返回值是QList<T>类型。
QList<int> values = map.values("plenty");
for (int i = 0; i < values.size(); ++i)
cout << values.at(i)<< endl;
3.4 QHash
QHash 是基于散列表来实现字典功能的模板类,QHash<Key,T>存储的键值对具有非常快的查找速度。
QHash与QMap的功能和用法相似,区别在于以下几点:
- QHash 比QMap的查找速度快;
- 在QMap上遍历时,数据项是按照键排序的,而QHash的数据项是任意顺序的;
- QMap的键必须提供“<”运算符,QHash的键必须提供“==”运算符和一个名称为qHash() 的全局散列函数。
3.5 QMultiHash
QMultiHash是QHash的子类,是用于处理多值映射的便利类,其用法与QMultiMap类似。