顺序容器: 通过元素在容器中的位置顺序存储和访问
- 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]; // one
QString 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()); // 3
QList<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, D
QList<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;
a
b
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:2
A:1
B:3