顺序容器: 通过元素在容器中的位置顺序存储和访问
- QList: 一般存指针
- QLinkedList
- QVector: 一般存对象
- QStack: 先进后出(栈)
- QQueue: 先进先出(队列)
关联容器: 通过键(key)存储和访问
- QMap: key唯一
- QMultiMap: key可重复
- QHash: key唯一,存储随机
- QMultiHash
- QSet: key与value相同
1. 顺序容器
QList
QList<QString> list;list.append("one");list.append("two");list.append("three");QString str1 = list[0]; // oneQString str2 = list.at(1); // two
QLinkedList
除了不提供下标索引的访问,和QList其它函数接口基本相同
QVector
函数接口与QList几乎相同,访问性能更高,因为是连续存储
QStack
先进后出(栈),LIFO
QStack<in> st;st.push(10);st.push(20);while (!st.isEmpty())qDebug("%d", st.pop);
QQueue
先进先出(队列),FIFO
QQueue<int> q;q.enqueue(10);q.enqueue(20);while (!q.isEmpty())qDebug("%d", q.dequeue);
QSet
QSet<QString> set;set<<"dog"<<"cat"<<"tiger";if (set.contains("cat"))qDebug("the set has a cat");
2. 关联容器
QMap
按键值顺序存储
QMap<QString, int> map;map["one"] = 1;map["two"] = 2;map.insert("three", 3);map.remove("two");int n1 = map["one"];int n3 = map.value("three");int timeout = map.value("timeout", 30);qDebug("%d %d %d", n1, n3, timeout);
QMultiMap
QMap的子类,键值可以重复
QMultiMap<QString, int) map1, map2, map3;map1.insert("plenty", 1000);map1.insert("plenty", 2000);map2.insert("plenty", 5000);map3 = map1 + map2;qDebug("%d", map3.size()); // 3QList<int> values = map3.values('plenty');foreach (int i,val)qDebug("%d", i); // 5000, 2000, 1000
2. 迭代器
Qt有两种迭代器:
- Java类型
- STL类型
2.1 Java 类型迭代器
| 容器类 | 只读迭代器 | 读写迭代器 |
|---|---|---|
| QList, QQueue | QListIterator | QMutableListIterator |
| QLinkedList | QLinkedListIterator | QMutableLinkedListIterator |
| QVector, QStack | QVectorIterator | QMutableVectorIterator |
| QSet | QSetiterator | QMutableSetiterator |
| QMap |
QMapiterator | QMutableMapiterator |
| QHash |
QHashIterator | QMutableHashIterator |
顺序容器类的使用:
QList<QString> list;list << "A" << "B" << "C";QListIterator<QString> i(list);while (i.hasNext()) // 判断在迭代器指针后面是否还有数据项qDebug() << i.next(); // 跳过一个数据项,并返回其值
也可以反向:
QListIterator<QString> i(list);i.toBack(); // 指针直接指到结尾while (i.hasPrevious())qDebug() << i.previous();
| 常用函数 | 功能 |
|---|---|
| void toFront() | 迭代器移动到列表最前面(第一个数据之前) |
| void toBack() | 迭代器移动到列表最后面(最后一个数据之后) |
| bool hasNext() | 如果迭代器不是位于列表最后位置,返回true |
| const T& next() | 返回下一个数据项,并且迭代器白后移一个位置 |
| const T& peekNext() | 返回一下个数据项,但是不移动迭代器位置 |
| bool hasPrevious() | 如果迭代器不是位于列表最前面,返回true |
| const T& previous() | 返回前一个数据项,并前移一个位置 |
| const T& peekPrevious() | 返回前一个数据项,但不移动 |
QListIterator 是只读访问,如要在遍历中修改,使用 QMutableListIterator:
- 删除奇数项:
QList<int> list;list << 1 << 2 << 3 << 4 << 5;QMutableListIterator<int> i(list);while (i.hasNext()) {if (i.next() % 2 != 0)i.remove();}
关联容器类的使用:
- 删除键(城市名)里的’city’ 结尾的数据项:
QMap<QString, QString> map;map.insert("Paris", "France");map.insert("New York", "USA");map.insert("Mexico City", "USA"); // 需要删除map.insert("Moscow", "Russia");...QMutableMapIterator<QString, QString> i(map);while (i.hasNext()) {if (i.next().key().endsWith("City"))i.remove();}
- 删除’value’是”USA”的项:
while (i.findNext("USA"))i.remove();
2.2 STL 类型迭代器
| 容器类 | 只读迭代器 | 读写迭代器 |
|---|---|---|
| QList, QQueue | QList::const_iterator | QList::iterator |
| QLinkedList | QLinkedList::const_iterator | QLinkedList::iterator |
| QVector, QStack | QVector::const_iterator | QVector::iterator |
| QSet | QSet::const_iterator | QSet::iterator |
| QMap |
QMap |
QMap |
可以使用 const_reverse_iterator 和 reverse_iterator 定义反向迭代器。
顺序容器类的使用:
QList<QString> list;list << "A" << "B" << "C" << "D";QList<QString>::const_iterator i;for (i = list.constBegin(); i != list:constEnd(); ++i)qDebug() << *; // A, B, C, DQList<QString>::reverse_iterator j;for (j = list.rbegin(); j != list.rend(); ++j) {*j = j->toLower();qDebug() << *j; // d, c, b, a}
关联容器类的使用:
QMap<int, int> map;map.insert(1, 11);map.insert(2, 22);QMap<int, int>::const_iterator i;for (i = map.constBegin(); i != map.constEnd(); ++i)qDebug() << i.key() << ":" << i.value();
QMultiMap<int, int> map;map.insert(1, 11);map.insert(2, 22);map.insert(2, 222);const QList<int> sizes = map.values(2); // 隐式共享(只有当sizes发生变化时,才复制一份出来)QList<int>::const_iterator i;for (i = sizes.begin(); i != sizes.end(); i++)qDebug() << *i;
下面的代码是错误的:
for (i = map.values(2).begin(); i != map.value(2).end(); i++)qDebug() << *i;
对于STL类型的迭代器,隐式共享还涉及另一个问题:
即当有一个迭代器在操作一个容器变量时,不要去复制这个容器变量。
foreach 关键字:
QLinkedList<QString> list;list.append("a");list.append("b");foreach (auto str, list)qDebug() << str;
ab
QMutliMap<QString, int> map;map.insert("A", 1);map.insert("A", 2);map.insert("B", 3);foreach (auto str, map.uniqueKeys()) {foreach (auto num, map.values(str))qDebug() << str << ":" << num;}
A:2A:1B:3
