概述

Qt提供了基于模板的容器类,这些容器类可以用于存储指定类型的数据项,Qt的容器类比标准模板库(STL)中的容器类更轻巧、安全和易于使用。它们还是线程安全的,它们作为只读容器时可被多个线程访问。
容器类是基于模板的类,如常用的容器类QList,T是一个具体的类型,可以是int,float等简单类型,也可以是QString,QData等类,但不能是QObject或任何其子类。T必须是一个可以赋值的类型,即T必须是一个缺省的构造函数,一个可复制构造函数的一个赋值运算符。

顺序容器类

QList

QList是最常用的容器,在其前后添加数据非常快,QList以下标索引的方式对数据项进行访问。
常用方法

  • insert():插入元素
  • replace():将索引位置i的元素替换为value
  • removeAt():删除索引位置i的元素
  • move():将索引位置的项从索引位置移动到索引位置
  • swap():用这个列表交换其他列表
  • append():在列表的末尾插入value
  • prepend():在列表的开头插入value
  • removeFirst():删除列表中的第一项
  • removeLast():删除列表中的最后一项
  • size():list大小
  • isEmpty():判断list是空
QList<QString> list;
list << "alpha" << "beta" << "delta";
list.insert(2, "gamma");

QList<QString> list;
list << "A" << "B" << "C" << "D" << "E" << "F";
list.move(1, 4);
// list: ["A", "C", "D", "E", "B", "F"]

QList<QString> list;
list.append("one");
list.append("two");
list.append("three");
// list: ["one", "two", "three"]

QList<QString> list;
list.prepend("one");
list.prepend("two");
list.prepend("three");
// list: ["three", "two", "one"]

迭代器

  • 只读迭代器:QList::const_iterator;
  • 读写迭代器:QList::iterator;
QList<QString> list;
list<<"A"<<"B"<<"C";
QList<QString>::const_iterator item;
for(item = list.constBegin(); item!=list.constEnd(); ++item) {
      qDebug()<<*item;
}

QLinkedList

是链式列表,数据项不是用连续的内存存储的,基于迭代器访问数据,并且插入和删除数据项的操作时间相同。除了不提供基于下标索引的数据项访问外,其他的方法与QList是相同的。
迭代器

  • 只读迭代器:QLinkedList::const_iterator;
  • 读写迭代器:QLinkedList::iterator;

QVector

提供动态数组的功能,以下标索引访问数据,函数接口与QList完全相同,性能比QList更高,QVector数据项是连续存储的。
迭代器

  • 只读迭代器:QVector::const_iterator;
  • 读写迭代器:QVector::iterator;

QStack

类似于堆栈的先进后出操作的容器类。

  • 入栈:push();
  • 出栈:pop();
QStack<int> stack;
stack.push(1);
stack.push(2);
stack.push(3);
while (!stack.isEmpty())
    cout << stack.pop() << Qt::endl;

QQueue

类似于队列先进先出操作的容器类。

  • 入队:enqueue();
  • 出队:dequeue();
QQueue<int> queue;
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
while (!queue.isEmpty())
    cout << queue.dequeue() << Qt::endl;

关联容器类

QMap

提供一个字典,一个键映射到一个值,存储数据是按照键的顺序,如果不在乎存储顺序,使用QHash更快。

map中添加数据

QMap<QString, int> map;
map["one"] = 1;
map["three"] = 3;
map["seven"] = 7;

map.insert("twelve", 12);

根据键查找值

int num1 = map["thirteen"];
int num2 = map.value("thirteen");
//如果找到键为"TIMEOUT"的就返回值,如果没有找到就返回30
int timeout = map.value("TIMEOUT", 30);

迭代器

  • 只读迭代器:QMap<key, T>::const_iterator;
  • 读写迭代器:QMap<key, T>::iterator;
for (QMap<int, QString>::const_iterator it = map.cbegin(), end = map.cend(); it != end; ++it) {
     cout << "The key: " << it.key() << Qt::endl
     cout << "The value: " << it.value() << Qt::endl;
     cout << "Also the value: " << (*it) << Qt::endl;
 }

QMultiMap

支持一个键关联多个值,是QMap的子类。

QMultiMap<QString, int> map1, map2, map3;

map1.insert("plenty", 100);
map1.insert("plenty", 2000);
// map1.size() == 2

map2.insert("plenty", 5000);
// map2.size() == 1

map3 = map1 + map2;
// map3.size() == 3

迭代器

  • 只读迭代器:QMap<key, T>::const_iterator;
  • 读写迭代器:QMap<key, T>::iterator;

QHash

使用散列函数进行查找,查找速度更快,功能和用法与QMap相似。
迭代器

  • 只读迭代器:QHash<key, T>::const_iterator;
  • 读写迭代器:QHash<key, T>::iterator;

QMultiHash

支持一个键关联多个值,使用散列函数进行查找,查找速度更快,是QHash的子类,用法与QMultiMap类似。
迭代器

  • 只读迭代器:QHash<key, T>::const_iterator;
  • 读写迭代器:QHash<key, T>::iterator;

QSet

基于散列表的集合模板类,存储数据的顺序是不定的,查找值的速度非常快,内部是QHash实现的。

QSet<QString> set;
set.insert("one");
set.insert("three");
set.insert("seven");

set << "twelve" << "fifteen" << "nineteen";

迭代器

  • 只读迭代器:QSet::const_iterator;
  • 读写迭代器:QSet::iterator;

QHash与QMap的区别

  1. QHash比QMap的查找速度快;
  2. 在QMap上遍历时,数据项是按照键排序的,而QHash的数据项是任意顺序的;
  3. QMap的键必须提供"<“运算符,QHash的键必须提供”=="运算符和一个名称为qHash()的全局散列函数;

begin() cbegin() constBegin() keyBegin()的区别

begin()

  • 返回一个指向容器中第一个元素的迭代器;
  • 如果容器为空,则返回的迭代器等于 end();
  • 通常用于在容器中迭代;

cbegin()

  • 返回一个常量迭代器,指向容器中的第一个元素;
  • 这个迭代器不能被修改,只能用于读取;
  • 与 begin() 的主要区别在于 cbegin() 返回的是常量迭代器;

constBegin()

  • 类似于 cbegin(),也返回一个指向容器中第一个元素的常量迭代器;
  • 主要用于在类中提供常量迭代器,而不需要外部调用者修改容器;

keyBegin()

  • 当涉及到像 QMap 这样的关联容器时,keyBegin() 返回一个指向容器中第一个键的迭代器;
  • 它通常用于遍历映射中的键;

:这些函数都是为了方便地在 Qt 的容器类中进行迭代。选择哪个函数取决于你的需求:如果你需要修改迭代器指向的元素,
使用 begin() 或 constBegin();如果你只需要读取数据,并且需要确保不修改,那么可以使用 cbegin() 或 constBegin();
而当你需要遍历映射中的键时,使用 keyBegin()

02-23 17:21