• 顺序容器: 通过元素在容器中的位置顺序存储和访问

    • QList: 一般存指针
    • QLinkedList
    • QVector: 一般存对象
    • QStack: 先进后出(栈)
    • QQueue: 先进先出(队列)
  • 关联容器: 通过键(key)存储和访问

    • QMap: key唯一
    • QMultiMap: key可重复
    • QHash: key唯一,存储随机
    • QMultiHash
    • QSet: key与value相同

1. 顺序容器

QList

  1. QList<QString> list;
  2. list.append("one");
  3. list.append("two");
  4. list.append("three");
  5. QString str1 = list[0]; // one
  6. QString str2 = list.at(1); // two

QLinkedList

除了不提供下标索引的访问,和QList其它函数接口基本相同

QVector

函数接口与QList几乎相同,访问性能更高,因为是连续存储

QStack

先进后出(栈),LIFO

  1. QStack<in> st;
  2. st.push(10);
  3. st.push(20);
  4. while (!st.isEmpty())
  5. qDebug("%d", st.pop);

QQueue

先进先出(队列),FIFO

  1. QQueue<int> q;
  2. q.enqueue(10);
  3. q.enqueue(20);
  4. while (!q.isEmpty())
  5. qDebug("%d", q.dequeue);

QSet

  1. QSet<QString> set;
  2. set<<"dog"<<"cat"<<"tiger";
  3. if (set.contains("cat"))
  4. qDebug("the set has a cat");

2. 关联容器

QMap

按键值顺序存储

  1. QMap<QString, int> map;
  2. map["one"] = 1;
  3. map["two"] = 2;
  4. map.insert("three", 3);
  5. map.remove("two");
  6. int n1 = map["one"];
  7. int n3 = map.value("three");
  8. int timeout = map.value("timeout", 30);
  9. qDebug("%d %d %d", n1, n3, timeout);

QMultiMap

QMap的子类,键值可以重复

  1. QMultiMap<QString, int) map1, map2, map3;
  2. map1.insert("plenty", 1000);
  3. map1.insert("plenty", 2000);
  4. map2.insert("plenty", 5000);
  5. map3 = map1 + map2;
  6. qDebug("%d", map3.size()); // 3
  7. QList<int> values = map3.values('plenty');
  8. foreach (int i,val)
  9. 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, QMultiMap QMapiterator QMutableMapiterator
QHash, QMultiHash QHashIterator QMutableHashIterator

顺序容器类的使用:

  1. QList<QString> list;
  2. list << "A" << "B" << "C";
  3. QListIterator<QString> i(list);
  4. while (i.hasNext()) // 判断在迭代器指针后面是否还有数据项
  5. qDebug() << i.next(); // 跳过一个数据项,并返回其值

也可以反向:

  1. QListIterator<QString> i(list);
  2. i.toBack(); // 指针直接指到结尾
  3. while (i.hasPrevious())
  4. 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:

  • 删除奇数项:
  1. QList<int> list;
  2. list << 1 << 2 << 3 << 4 << 5;
  3. QMutableListIterator<int> i(list);
  4. while (i.hasNext()) {
  5. if (i.next() % 2 != 0)
  6. i.remove();
  7. }

关联容器类的使用:

  • 删除键(城市名)里的’city’ 结尾的数据项:
  1. QMap<QString, QString> map;
  2. map.insert("Paris", "France");
  3. map.insert("New York", "USA");
  4. map.insert("Mexico City", "USA"); // 需要删除
  5. map.insert("Moscow", "Russia");
  6. ...
  7. QMutableMapIterator<QString, QString> i(map);
  8. while (i.hasNext()) {
  9. if (i.next().key().endsWith("City"))
  10. i.remove();
  11. }
  • 删除’value’是”USA”的项:
  1. while (i.findNext("USA"))
  2. 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, QMultiMap QMap::const_iterator QMap::iterator

可以使用 const_reverse_iteratorreverse_iterator 定义反向迭代器。

顺序容器类的使用:

  1. QList<QString> list;
  2. list << "A" << "B" << "C" << "D";
  3. QList<QString>::const_iterator i;
  4. for (i = list.constBegin(); i != list:constEnd(); ++i)
  5. qDebug() << *; // A, B, C, D
  6. QList<QString>::reverse_iterator j;
  7. for (j = list.rbegin(); j != list.rend(); ++j) {
  8. *j = j->toLower();
  9. qDebug() << *j; // d, c, b, a
  10. }

关联容器类的使用:

  1. QMap<int, int> map;
  2. map.insert(1, 11);
  3. map.insert(2, 22);
  4. QMap<int, int>::const_iterator i;
  5. for (i = map.constBegin(); i != map.constEnd(); ++i)
  6. qDebug() << i.key() << ":" << i.value();
  1. QMultiMap<int, int> map;
  2. map.insert(1, 11);
  3. map.insert(2, 22);
  4. map.insert(2, 222);
  5. const QList<int> sizes = map.values(2); // 隐式共享(只有当sizes发生变化时,才复制一份出来)
  6. QList<int>::const_iterator i;
  7. for (i = sizes.begin(); i != sizes.end(); i++)
  8. qDebug() << *i;

下面的代码是错误的:

  1. for (i = map.values(2).begin(); i != map.value(2).end(); i++)
  2. qDebug() << *i;

对于STL类型的迭代器,隐式共享还涉及另一个问题:
即当有一个迭代器在操作一个容器变量时,不要去复制这个容器变量。

foreach 关键字:

  1. QLinkedList<QString> list;
  2. list.append("a");
  3. list.append("b");
  4. foreach (auto str, list)
  5. qDebug() << str;
  1. a
  2. b
  1. QMutliMap<QString, int> map;
  2. map.insert("A", 1);
  3. map.insert("A", 2);
  4. map.insert("B", 3);
  5. foreach (auto str, map.uniqueKeys()) {
  6. foreach (auto num, map.values(str))
  7. qDebug() << str << ":" << num;
  8. }
  1. A:2
  2. A:1
  3. B:3