【QT】容器类

目录

1.容器类概述

2.顺序容器类

2.1 QList

2.2 QLinkedList

2.3 QVector

2.4 QStack

2.5 QQueue

3.关联容器类

3.1 QSet

3.2 QMap

3.3 QMultiMap

3.4 QHash

3.5 QMuItiHash

1.容器类概述

  • Qt提供了多个基于模板的容器类,这些容器类可以用于存储指定类型的数据项。
  • Qt的容器类比标准模板库(STL)中的容器类更轻巧、安全和易于使用。这些容器类是隐式共享和可重入的,而且它们进行了速度和存储优化,因此可以减少可执行文件的大小。此外,它们还是线程安全的,也就是说它们作为只读容器时可被多个线程访问。
  • Qt的容器类分为顺序容器(sequentialcontainers)和关联容器(associativecontainers)。
  • 容器迭代类用于遍历容器里的数据项,有Java类型的迭代类和STL类型的迭代类。Java类型的迭代类易于使用,提供高级功能,而STL类型的迭代类效率更高一些。Qt还提供了foreach宏用于遍历容器内的所有数据项。

2.顺序容器类

2.1 QList

QList是最常用的容器类,虽然它是以数组列表(array-list)的形式实现的,但是在其前或后
添加数据非常快,QList以下标索引的方式对数据项进行访问。
容器类QList<T>,T是一个具体的类型,可以是int、float等简单类型,也可以是Qstring、QDate等类,但 不能是QObject或任何其子类。 在存储QObject对象及其子类对象时,不能直接存对象本身,而是只能存对象的地址。T必须是一个可赋值的类型,即T必须提供一个缺省的构造函数,一个可复制构造函数和一个赋值运算符。
(1)声明 QList
//基本数据类型
QList<int> integerList;
QList<QDate> dateList;
//存储QObject对象的地址
QList <QWidget *> ptr_widgets;
QList <QObject *> ptr_objects;
(2)初始化 QList
QList<QString> list = { "one", "two", "three" };
QWidget * widget1 = new QWidget();
QWidget * widget2 = new QWidget();
QList<QWidget *> ptr_widgets = {widget1, widget2};
(3)QList 基本的添加、插入、替换、删除、移动、修改
1. 增加节点
insert():插入节点到
append():尾部添加节点
prepend() :头部添加节点
operator <<():尾部添加节点或链表
operator+=():尾部添加节点
2. 删除节点
removeAt():删除节点
removeFirst():删除头节点
removeLast():删除尾节点
3. 移动节点
move():链表内移动节点位置
swap():俩个链表交换值(其实交换一下地址映射就能实现)
4. 修改节点值
replace():替换链表内的节点值
(4)QList 定位节点
QList是有序的链表,可以通过索引来得到。
1. operator [ ] 数组索引符:这个和普通数组一样的使用 [ ] 访问下标方法一致
2. at() 函数:也是通过索引值,也即是下标方式
Qt 推荐使用at()函数,这样的效率更好,因为 at()函数不会发生 深拷贝 ,而另外一种方式会。
QList还提供了一些快捷的 索引 + 返回索引节点 + 删除原索引节点,也就是组合的功能;但是这个是 take…不是get…这样的,这就意味着,这个其实是剪掉一个节点,并返回。
3. takeAt():取得在指定位置的节点
4. takeFirst():取得头节点 ;等价【takeAt(0)】
5. takeLast():取得尾节点
(5)基本常用函数
contains():是否包含节点xxx
count():对指定节点值计数
isEmpty():链表为空
size():链表大小
indexOf():节点位置

2.2 QLinkedList

QLinkedList<T>是链式列表(linked-list)(双向链表容器类),数据项不是用连续的内存存储的,它基于迭代器访问数据项,并且插入和删除数据项的操作时间相同。除了不提供基于下标索引的数据项访问外,QLinkedList的其他接口函数与QList基本相同。

(1)重要特性如下:

  • 动态大小:QLinkedList 的大小是动态的,可以根据需要轻松添加或删除元素。这使得它在处理具有不确定大小的数据集时非常有用。

  • 双向遍历:与 QVector 和 QList 不同,QLinkedList 允许从头到尾以及从尾到头的双向遍历。这种遍历方式在某些场景下会非常有用。

  • 高效的插入和删除操作:在链表的中间插入或删除元素的时间复杂度为 O(1)。这使得 QLinkedList 在需要频繁插入和删除元素的场景中,具有优势。

  • 不需要连续内存:与 QVector 和 QList 相比,QLinkedList 的元素不需要存储在连续的内存空间中。这意味着在内存碎片化的情况下,QLinkedList 可能更容易分配内存。

(2)常用接口

构造函数和析构函数:

  • QLinkedList(): 创建一个空的 QLinkedList。

  • QLinkedList(const QLinkedList<T> &other): 复制构造函数,用另一个 QLinkedList 对象来创建一个新的对象。

  • ~QLinkedList(): 析构函数,用于释放资源。

容量相关接口:

  • bool isEmpty() const: 返回链表是否为空。

  • int size() const: 返回链表中元素的数量。

元素访问接口:

  • T &first(): 返回链表中第一个元素的引用。

  • const T &first() const: 返回链表中第一个元素的常量引用。

  • T &last(): 返回链表中最后一个元素的引用。

  • const T &last() const: 返回链表中最后一个元素的常量引用。

修改接口:

  • void append(const T &value): 在链表末尾添加一个元素。

  • void prepend(const T &value): 在链表开头添加一个元素。

  • void insert(int i, const T &value): 在链表的指定位置插入一个元素。

  • void removeFirst(): 移除链表中的第一个元素。

  • void removeLast(): 移除链表中的最后一个元素。

  • bool removeOne(const T &value): 移除链表中第一个与指定值相等的元素,如果成功移除则返回 true,否则返回 false。

  • int removeAll(const T &value): 移除链表中所有与指定值相等的元素,返回移除的元素个数。

  • void clear(): 清空链表。

查找接口:

  • bool contains(const T &value) const: 检查链表是否包含指定值的元素。

  • int count(const T &value) const: 返回链表中指定值的元素个数。

  • int indexOf(const T &value, int from = 0) const: 返回链表中指定值的第一个元素的索引,如果未找到则返回 -1。

  • int lastIndexOf(const T &value, int from = -1) const: 返回链表中指定值的最后一个元素的索引,如果未找到则返回 -1。

迭代器:

  • iterator begin(): 返回指向链表第一个元素的迭代器。

  • const_iterator begin() const: 返回指向链表第一个元素的常量迭代器。

  • iterator end(): 返回指向链表末尾的迭代器。

  • const_iterator end() const 返回指向链表末尾的常量迭代器。

  • const_iterator cbegin() const: 返回指向链表第一个元素的常量迭代器。

  • const_iterator cend() const: 返回指向链表末尾的常量迭代器。

  • reverse_iterator rbegin(): 返回指向链表最后一个元素的反向迭代器。

  • const_reverse_iterator rbegin() const: 返回指向链表最后一个元素的常量反向迭代器。

  • reverse_iterator rend(): 返回指向链表起始位置之前的反向迭代器。

  • const_reverse_iterator rend() const: 返回指向链表起始位置之前的常量反向迭代器。

  • const_reverse_iterator crbegin() const: 返回指向链表最后一个元素的常量反向迭代器。

  • const_reverse_iterator crend() const: 返回指向链表起始位置之前的常量反向迭代器。

比较操作:

  • bool operator==(const QLinkedList<T> &other) const: 判断两个链表是否相等(元素数量和对应元素相等)。

  • bool operator!=(const QLinkedList<T> &other) const: 判断两个链表是否不等。

赋值操作:

  • QLinkedList<T> &operator=(const QLinkedList<T> &other): 为当前链表赋值另一个链表的内容。

其他接口:

  • void swap(QLinkedList<T> &other): 交换两个链表的内容。

注意:在使用 QLinkedList 时,应确保所存储的元素类型支持复制构造函数和赋值操作。对于大型数据结构,如果不需要频繁插入和删除元素,可以考虑使用 QVector 以获得更好的内存管理和性能。

(3)QLinkedList 常见操作

 插入元素:

QLinkedList<int> list;

list.append(1);

list.append(2);

list.append(3);

list.prepend(0); // 在开始处插入元素

删除元素:

list.removeAll(1); // 删除所有值为 1 的元素

list.removeFirst(); // 删除第一个元素

list.removeLast(); // 删除最后一个元素

访问元素:

int first = list.first(); // 获取第一个元素

int last = list.last(); // 获取最后一个元素

查找元素:

QLinkedList<int>::iterator it = std::find(list.begin(), list.end(), 2); // 查找值为 2 的元素

if (it != list.end()) {

    qDebug() << "Found:" << *it;

}

反转链表(C++14 及以上):

std::reverse(list.begin(), list.end());

排序链表:

std::sort(list.begin(), list.end()); // 默认升序排序

自定义排序:

auto descendingOrder = [](int a, int b) { return a > b; };

std::sort(list.begin(), list.end(), descendingOrder); // 降序排序

迭代器遍历:

QLinkedList<int>::iterator it;

for (it = list.begin(); it != list.end(); ++it) {

    qDebug() << *it;

}

使用 Java 风格迭代器:

QLinkedListIterator<int> it(list);

while (it.hasNext()) {

    qDebug() << it.next();

}

使用常量迭代器(只读访问):

QLinkedList<int>::const_iterator cit;

for (cit = list.constBegin(); cit != list.constEnd(); ++cit) {

    qDebug() << *cit;

}

2.3 QVector

QVector<T>提供动态数组的功能,以下标索引访问数据。

QVector的函数接口与QList几乎完全相同,QVector<T>的性能比QList<T>更高,因为

QVector<T>的数据项是连续存储的。

(1)常用接口

构造函数:

  • QVector():创建一个空的 QVector 容器。

  • QVector(int size):创建一个指定大小的 QVector 容器。

  • QVector(int size, const T &value):创建一个指定大小的 QVector 容器,并用给定值填充。

  • QVector(const QVector<T> &other):复制构造函数,用另一个 QVector 容器创建一个新的 QVector 容器。

元素访问:

  • T &operator[](int i):通过索引访问元素,返回指定索引处的元素的引用。

  • const T &operator[](int i) const:以只读方式通过索引访问元素。

  • T &at(int i):通过索引访问元素,会检查索引是否越界。

  • T &front():返回容器中的第一个元素的引用。

  • const T &front() const:以只读方式返回容器中的第一个元素。

  • T &back():返回容器中的最后一个元素的引用。

  • const T &back() const:以只读方式返回容器中的最后一个元素。

容量和大小:

  • bool isEmpty() const:判断容器是否为空。

  • int size() const:获取容器中元素的数量。

  • int capacity() const:获取容器的容量。

  • void reserve(int size):预分配指定数量的元素空间,提高性能。

  • void squeeze():释放未使用的容量,将容量调整为实际元素数量。

修改容器:

  • void clear():清空容器中的所有元素。

  • void resize(int size):调整容器的大小。

  • void fill(const T &value, int size = -1):用给定值填充容器,可以指定填充个数。

  • void append(const T &value):在容器末尾添加一个元素。

  • void prepend(const T &value):在容器开头添加一个元素。

  • void insert(int i, const T &value):在指定位置插入一个元素。

  • void replace(int i, const T &value):替换指定位置的元素。

  • void remove(int i):移除指定位置的元素。

  • void remove(int i, int count):从指定位置开始移除指定数量的元素。

  • void removeAll(const T &value):移除容器中所有等于给定值的元素。

  • bool removeOne(const T &value):移除容器中第一个等于给定值的元素。

查找:

  • int indexOf(const T &value, int from = 0) const:从指定位置开始查找给定值的元素,返回第一个找到的元素的索引。

  • int lastIndexOf(const T &value, int from = -1) const:从指定位置开始向前查找给定值的元素,返回第一个找到的元素的索引。

  • bool contains(const T &value) const:判断容器中是否包含给定值的元素。

  • int count(const T &value) const:计算容器中给定值的元素的个数。

排序:

  • void sort(Qt::SortOrder order = Qt::AscendingOrder):对容器中的元素进行排序,可以指定升序或降序。

  • void stableSort(Qt::SortOrder order = Qt::AscendingOrder):对容器中的元素进行稳定排序,可以指定升序或降序。

迭代器:

  • iterator begin():返回容器的起始迭代器。

  • const_iterator begin() const:返回容器的只读起始迭代器。

  • iterator end():返回容器的结束迭代器。

  • const_iterator end() const:返回容器的只读结束迭代器。

比较操作符:

  • bool operator==(const QVector<T> &other) const:判断两个 QVector 容器是否相等,元素数量和值都相等时为 true。

  • bool operator!=(const QVector<T> &other) const:判断两个 QVector 容器是否不相等。

其他功能:

  • QVector<T> &operator=(const QVector<T> &other):赋值操作符,将一个 QVector 容器赋值给另一个。

  • QVector<T> mid(int pos, int length = -1) const:获取容器中指定范围的元素,返回一个新的 QVector 容器。

  • void swap(QVector<T> &other):交换两个 QVector 容器的内容。

(2)QVector示例

#include <QVector>
#include <QDebug>int main()
{// 创建一个 QVector 容器,并添加元素QVector<int> vec;vec.append(3);vec.append(1);vec.append(4);vec.append(2);qDebug() << "Original QVector:";for (int i = 0; i < vec.size(); ++i) {qDebug() << vec.at(i);}// 使用排序功能vec.sort(Qt::AscendingOrder);qDebug() << "Sorted QVector:";for (int i = 0; i < vec.size(); ++i) {qDebug() << vec.at(i);}// 插入元素vec.insert(1, 8); // 在索引 1 位置插入值 8qDebug() << "QVector after inserting 8 at index 1:";for (int i = 0; i < vec.size(); ++i) {qDebug() << vec.at(i);}// 删除元素vec.remove(2); // 删除索引 2 处的元素qDebug() << "QVector after removing the element at index 2:";for (int i = 0; i < vec.size(); ++i) {qDebug() << vec.at(i);}// 查找元素int index = vec.indexOf(4);if (index != -1) {qDebug() << "Element 4 found at index:" << index;} else {qDebug() << "Element 4 not found";}return 0;
}

2.4 QStack

QStack<T>是提供类似于堆栈的后入先出(LIFO)操作的容器类,可以存储任何类型的数据,QStack使用动态数组来实现数据的存储,push()和pop()是主要的接口函数。QStack继承了QVector,所以它拥有QVector的所有功能,同时提供了堆栈的特定操作。

(1)常用接口

  • 构造函数:QStack() 创建一个空的QStack实例。

  • void push(const T &value):将元素value压入堆栈的顶部。

  • T pop():移除并返回堆栈顶部的元素。当堆栈为空时,调用此方法会导致未定义行为。

  • T &top():返回堆栈顶部的元素的引用。当堆栈为空时,调用此方法会导致未定义行为。

  • const T &top() const:返回堆栈顶部元素的const引用。当堆栈为空时,调用此方法会导致未定义行为。

  • bool isEmpty() const:如果堆栈为空,则返回true;否则返回false。

  • int size() const:返回堆栈中元素的数量。

  • void clear():清空堆栈,移除所有元素。

  • QStack<T> &operator+=(const T &value):将元素value压入堆栈的顶部,与push()方法功能相同。

  • QStack<T> &operator<<(const T &value):将元素value压入堆栈的顶部,与push()方法功能相同。

(2) QStack 示例

#include <QCoreApplication>
#include <QStack>
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建一个空的QStack实例QStack<int> stack;// 使用push()压入元素stack.push(10);stack.push(20);stack.push(30);// 使用top()查看栈顶元素qDebug() << "Top element:" << stack.top(); // 输出:Top element: 30// 使用size()查看堆栈大小qDebug() << "Stack size:" << stack.size(); // 输出:Stack size: 3// 使用pop()移除并返回栈顶元素int poppedValue = stack.pop();qDebug() << "Popped value:" << poppedValue; // 输出:Popped value: 30// 使用isEmpty()检查堆栈是否为空qDebug() << "Stack is empty:" << (stack.isEmpty() ? "Yes" : "No"); // 输出:Stack is empty: No// 使用operator<<压入元素stack << 40 << 50;// 使用clear()清空堆栈stack.clear();qDebug() << "Stack is empty after clear():" << (stack.isEmpty() ? "Yes" : "No"); // 输出:Stack is empty after clear(): Yesreturn a.exec();
}

2.5 QQueue

QQueue<T>是提供类似于队列先入先出(FIFO)操作的容器类。这种特性使得队列在处理一些需要按顺序执行任务的场景中表现出优越性。QQueue继承自QList,因此可以方便地利用QList的功能实现队列的基本操作。

(1)重要特性

  • 任务调度:在操作系统或多线程应用中,QQueue可用于实现任务调度器,确保任务按照预定的顺序执行,避免资源竞争和死锁问题。

  • 消息队列:在分布式系统或网络应用中,QQueue可以作为消息队列用于缓存和传输消息,确保消息的有序到达和处理。

  • 数据缓冲:在数据处理和传输过程中,QQueue可以作为缓冲区,允许数据在生产者和消费者之间异步传输,提高系统的吞吐量和响应速度。

  • 事件处理:在GUI应用程序中,QQueue可以用于实现事件队列,确保用户界面按顺序响应用户的操作。

(2)常用接口

  • QQueue():构造函数,创建一个空的队列。

  • ~QQueue():析构函数,销毁队列及其所有元素。

  • void enqueue(const T &value):将值value添加到队列的末尾。

  • T dequeue():从队列的头部移除并返回第一个元素。如果队列为空,这个函数的行为是未定义的。

  • T &head():返回队列头部元素的引用。如果队列为空,这个函数的行为是未定义的。

  • const T &head() const:返回队列头部元素的只读引用。如果队列为空,这个函数的行为是未定义的。

  • bool isEmpty() const:返回队列是否为空的布尔值。

  • int size() const:返回队列中的元素个数。

  • void clear():清空队列中的所有元素。

  • bool contains(const T &value) const:检查队列是否包含特定值value。

  • int count(const T &value) const:返回队列中特定值value的个数。

  • T &first():返回队列中第一个元素的引用。如果队列为空,这个函数的行为是未定义的。

  • const T &first() const:返回队列中第一个元素的只读引用。如果队列为空,这个函数的行为是未定义的。

  • T &last():返回队列中最后一个元素的引用。如果队列为空,这个函数的行为是未定义的。

  • const T &last() const:返回队列中最后一个元素的只读引用。如果队列为空,这个函数的行为是未定义的。

(3)QQueue示例

#include <QCoreApplication>
#include <QQueue>
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 1. 创建一个空的QQueue对象QQueue<int> queue;// 2. 入队元素queue.enqueue(10);queue.enqueue(20);queue.enqueue(30);// 3. 获取队列大小qDebug() << "Queue size:" << queue.size(); // 输出:Queue size: 3// 4. 检查队列是否为空qDebug() << "Queue is empty:" << queue.isEmpty(); // 输出:Queue is empty: false// 5. 查看队列的头部元素qDebug() << "Queue head:" << queue.head(); // 输出:Queue head: 10// 6. 出队元素int firstElement = queue.dequeue();qDebug() << "Dequeued element:" << firstElement; // 输出:Dequeued element: 10// 7. 获取队列中的第一个和最后一个元素qDebug() << "First element:" << queue.first(); // 输出:First element: 20qDebug() << "Last element:" << queue.last(); // 输出:Last element: 30// 8. 检查队列是否包含特定值qDebug() << "Queue contains 20:" << queue.contains(20); // 输出:Queue contains 20: true// 9. 计算队列中特定值的个数qDebug() << "Count of 20 in queue:" << queue.count(20); // 输出:Count of 20 in queue: 1// 10. 清空队列queue.clear();qDebug() << "Queue size after clear:" << queue.size(); // 输出:Queue size after clear: 0return a.exec();
}

3.关联容器类

3.1 QSet

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

QSet的重要性在于其高性能特性,这使得它成为处理大量数据时的理想选择。例如,在进行文本分析时,我们可能需要追踪大量独特的单词,QSet可以用于此类任务,以便快速检索和添加新单词。同样,QSet在编译器优化、数据库查询优化和网络应用中也发挥着关键作用。

(1)常用接口

构造函数和析构函数:

  • QSet():创建一个空的 QSet。

  • QSet(const QSet<T> &other):拷贝构造函数,用于创建一个与 other 相同的 QSet。

  • ~QSet():析构函数,用于释放 QSet 占用的内存。

添加元素:

void insert(const T &value):将值插入 QSet。如果值已存在,不会插入重复值。

删除元素:

  • int remove(const T &value):删除 QSet 中等于 value 的元素,返回删除的元素个数(0 或 1)。

  • void clear():删除 QSet 中的所有元素。

查询元素:

  • bool contains(const T &value) const:检查 QSet 是否包含与 value 相等的元素,如果包含返回 true,否则返回 false。

  • int count(const T &value) const:返回 QSet 中与 value 相等的元素个数。

  • int size() const:返回 QSet 中的元素个数。

遍历元素:

  • QSetIterator<T> begin() const:返回指向 QSet 中第一个元素的迭代器。

  • QSetIterator<T> end() const:返回指向 QSet 中最后一个元素之后位置的迭代器。

操作符重载:

  • QSet<T> &operator+=(const T &value):将 value 添加到 QSet 中,如果已存在则不添加,返回 *this。

  • QSet<T> &operator-=(const T &value):从 QSet 中移除与 value 相等的元素,返回 *this。

  • QSet<T> &operator|=(const QSet<T> &other):将 other 中的所有元素添加到 QSet 中,返回 *this。

  • QSet<T> &operator&=(const QSet<T> &other):保留 QSet 中与 other 的交集元素,返回 *this。

  • QSet<T> &operator^=(const QSet<T> &other):将 QSet 中与 other 不相交的元素进行合并,返回 *this。

集合操作:

  • QSet<T> unite(const QSet<T> &other) const:返回 QSet 与 other 的并集。

  • QSet<T> intersect(const QSet<T> &other) const:返回 QSet 与 other 的交集。

  • QSet<T> subtract(const QSet<T> &other) const:返回 QSet 与 other 的差集。

  • QSet<T> symmetricDifference(const QSet<T> &other) const:返回 QSet 与 other 的对称差集(只存在于一个集合中的元素)。

注意:QSet 的元素类型 T 必须提供 qHash(const T &) 函数以及重载 operator== 以支持元素的比较和哈希。

(2)QSet示例

#include <QSet>
#include <QString>
#include <QDebug>int main() {// 创建空 QSetQSet<QString> set;// 添加元素set.insert("apple");set.insert("banana");set.insert("orange");// 检查元素是否包含在 QSet 中if (set.contains("banana")) {qDebug() << "Set contains banana";}// QSet 中的元素个数qDebug() << "Size of set:" << set.size();// 遍历 QSet 中的元素for (const QString &value : set) {qDebug() << value;}// 删除元素set.remove("apple");// 检查 QSet 是否包含已删除的元素if (!set.contains("apple")) {qDebug() << "Apple has been removed from the set";}// 使用操作符重载QSet<QString> set2;set2.insert("cherry");set2.insert("banana");QSet<QString> unitedSet = set | set2; // 并集QSet<QString> intersectedSet = set & set2; // 交集QSet<QString> differenceSet = set - set2; // 差集QSet<QString> symmetricDiffSet = set ^ set2; // 对称差集qDebug() << "United set:" << unitedSet;qDebug() << "Intersected set:" << intersectedSet;qDebug() << "Difference set:" << differenceSet;qDebug() << "Symmetric difference set:" << symmetricDiffSet;// 清空 QSetset.clear();qDebug() << "Size of set after clearing:" << set.size();return 0;
}

3.2 QMap

QMap<Key,T>提供一个字典(关联数组),一个键映射到一个值。QMap内部使用平衡二叉树(红黑树)作为底层数据结构,提供了高效的插入、删除和查找操作。QMap存储数据是按照键的顺序,如果不在乎存储顺序,使用QHash会更快。

(1)应用场景

  • 字典和映射:QMap可以用作字典或映射,将一组键与相应的值相关联。这可以用于存储和检索配置设置、用户数据、缓存等。

  • 排序数据:QMap内部按照键的顺序对数据进行排序。这使得QMap在需要对数据进行排序的场景下非常合适。插入新数据时,QMap会自动将其插入到正确的位置。

  • 索引和计数:QMap可以用于对数据进行索引和计数。例如,统计文本中每个单词出现的次数或将项目ID映射到项目详细信息。

  • 数据分组和聚合:QMap可以用于对数据进行分组和聚合。例如,将订单数据按照客户进行分组或将学生按照班级进行分组。

  • 配置和属性存储:QMap可以用于存储配置数据或对象的属性。例如,将设置名称映射到设置值或将对象ID映射到对象属性。

(2)常用接口

  • insert(key, value):向QMap中插入一个键值对。如果已存在具有相同键的条目,则用新值替换旧值。

  • remove(key):从QMap中删除与给定键关联的条目。

  • erase(key):从QMap中删除与给定键关联的条目。

  • contains(key):检查QMap是否包含与给定键关联的条目。

  • value(key):返回与给定键关联的值。如果找不到键,则返回默认构造的值。

  • keys():返回QMap中所有键的列表。

  •  values():返回QMap中所有值的列表。

  • size():返回QMap中的条目数。

  • isEmpty():检查QMap是否为空。

  • clear():清空QMap中的所有条目。

(3)QMap示例

#include <QCoreApplication>
#include <QMap>
#include <QString>
#include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 创建QMap并插入键值对QMap<QString, int> map;map.insert("one", 1);map.insert("two", 2);map.insert("three", 3);qDebug() << "Initial QMap: " << map;// 检查QMap是否包含某个键if (map.contains("two")) {qDebug() << "QMap contains key 'two'";}// 获取键对应的值int value = map.value("two");qDebug() << "Value for key 'two': " << value;//在使用value()函数查找键值时,还可以指定一个缺省的返回值,示例如下:map.value("four",4);//这表示如果在map里找到键“four”,就返回关联的值,否则返回值为4。// 获取所有键和值QList<QString> keys = map.keys();QList<int> values = map.values();qDebug() << "Keys: " << keys;qDebug() << "Values: " << values;// 获取QMap大小int size = map.size();qDebug() << "Size of QMap: " << size;// 删除键值对map.remove("two");qDebug() << "QMap after removing key 'two': " << map;// 使用迭代器遍历QMapqDebug() << "Iterating through QMap:";QMap<QString, int>::const_iterator i;for (i = map.constBegin(); i != map.constEnd(); ++i) {qDebug() << i.key() << ": " << i.value();}// 清空QMapmap.clear();qDebug() << "QMap after clearing: " << map;return a.exec();
}

3.3 QMultiMap

QMultiMap是QMap的子类,是用于处理多值映射的便利类。多值映射就是一个键可以对应多个值。这种数据结构典型的用例包括但不限于:管理分组的数据、实现多值字典、存储键值对数据等。QMap正常情况下不允许多值映射,除非使用QMap::insertMulti()添加键值对。QMultiMap是QMap的子类,所以QMap的大多数函数在QMultiMap都是可用的,但是有几个特殊的,QMultiMap::insert()等效于QMap::insertMulti(),QMultiMap::replace()等效于QMap::insert()。

(1)常用接口

插入和删除:

  • insert:向 QMultiMap 中插入一个键值对。如果已经存在具有相同键的键值对,则新的键值对将被添加到已有键值对之后。

  • insertMulti:类似于 insert,但返回指向新插入键值对的迭代器。

  • remove:从 QMultiMap 中删除与指定键和值匹配的所有键值对。返回被删除键值对的数量。

  • clear:清除 QMultiMap 中的所有键值对。

查找:

  • value:返回与指定键关联的第一个值。如果找不到匹配的键,则返回默认值。

  • values:返回与指定键关联的所有值的列表。

  • count:返回与指定键关联的值的数量。

  • find:返回指向与指定键关联的第一个值的迭代器。如果找不到匹配的键,则返回 end()。

  • begin、end:返回指向 QMultiMap 开始或结束位置的迭代器。

  • erase:删除指定位置的键值对,并返回指向下一个键值对的迭代器。

大小和容量:

  • isEmpty:判断 QMultiMap 是否为空。

  • size、count:返回 QMultiMap 中的键值对数量。

键和值:

  • keys:返回 QMultiMap 中所有键的列表。可以通过传入一个值参数来获得与指定值关联的所有键。

  • values:返回 QMultiMap 中所有值的列表。

  • unite:将另一个 QMultiMap 的键值对添加到当前 QMultiMap 中。如果两个 QMultiMap 中具有相同的键,则将值合并到一个键下。

比较操作:

  • operator==、operator!=:比较两个 QMultiMap 是否相等或不等。

STL 风格迭代器:

  • QMultiMap 提供了类似 STL 的迭代器接口,如 begin、end、constBegin、constEnd 等,使得用户可以方便地遍历和操作键值对。

(2)QMultiMap示例

#include <QCoreApplication>
#include <QMultiMap>
#include <QDebug>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 1. 创建一个空的 QMultiMap 对象QMultiMap<QString, int> ageMap;// 2. 使用 insert 插入键值对ageMap.insert("Alice", 25);ageMap.insert("Bob", 30);ageMap.insert("Charlie", 22);ageMap.insert("Bob", 35); // 允许有相同的键// 3. 使用 insertMulti 插入键值对ageMap.insertMulti("Alice", 26);// 4. 遍历 QMultiMapfor (auto it = ageMap.begin(); it != ageMap.end(); ++it) {qDebug() << it.key() << ": " << it.value();}// 5. 使用 value 获取第一个匹配的值qDebug() << "First value for Alice: " << ageMap.value("Alice");// 6. 使用 values 获取所有匹配的值QList<int> aliceAges = ageMap.values("Alice");qDebug() << "All values for Alice: " << aliceAges;// 7. 使用 count 获取键的数量qDebug() << "Count for Alice: " << ageMap.count("Alice");// 8. 使用 find 获取匹配键的迭代器auto it = ageMap.find("Bob");if (it != ageMap.end()) {qDebug() << "Found Bob: " << it.value();}// 9. 使用 erase 删除一个键值对ageMap.erase(ageMap.find("Charlie"));// 10. 使用 remove 删除所有匹配的键值对ageMap.remove("Alice");// 11. 检查 QMultiMap 是否为空qDebug() << "Is empty: " << ageMap.isEmpty();// 12. 获取 QMultiMap 的大小qDebug() << "Size: " << ageMap.size();// 13. 获取所有键和值qDebug() << "Keys: " << ageMap.keys();qDebug() << "Values: " << ageMap.values();// 14. 使用 unite 合并两个 QMultiMapQMultiMap<QString, int> anotherAgeMap;anotherAgeMap.insert("Diana", 28);ageMap.unite(anotherAgeMap);qDebug() << "After unite: " << ageMap;// 15. 清空 QMultiMapageMap.clear();qDebug() << "Size after clear: " << ageMap.size();return a.exec();
}

3.4 QHash

QHash是基于散列表来实现字典功能的模板类,QHash<Key,T>存储的键值对具有非常快的

查找速度。

QHash与QMap的功能和用法相似,区别在于以下几点:

  • QHash比QMap的查找速度快;

  • 在QMap上遍历时,数据项是按照键排序的,而QHash的数据项是任意顺序的;

  • QMap的键必须提供“<”运算符,QHash的键必须提供“一”运算符和一个名称为qHash()

的全局散列函数。

(1)常用接口

插入: QMap 支持多种插入方法,例如:

  • insert():插入一个键值对,如果已存在相同的键,则值将被替换。

  • insertMulti():插入一个键值对,即使存在相同的键,值也会被保留。

QMap<QString, int> map;

map.insert("apple", 1);

map.insert("banana", 2);

map.insertMulti("apple", 3);

自定义哈希函数: QHash 允许你为自定义类型提供哈希函数。你需要为你的类型实现一个名为 qHash 的全局函数,该函数接受你的类型作为参数并返回一个 uint 值。

uint qHash(const CustomType &key, uint seed = 0) noexcept;

自定义比较函数: QHash 默认使用 operator== 进行键值比较。如果你需要使用自定义比较函数,可以使用 QHash 的一个变体——QHashF,它接受一个自定义的比较函数对象。

QHash<Key, Value, KeyEqual> hash;

容量管理: QHash 允许你控制其底层哈希表的大小。使用 reserve() 函数预分配空间可以避免不必要的重新哈希。此外,capacity() 函数可以获取当前的容量,squeeze() 函数可以收缩容量以适应当前的元素数量。

hash.reserve(100);

int cap = hash.capacity();

hash.squeeze();

QMultiHash: QHash 不允许多个键关联到同一个值。QMultiHash 允许这种关联,支持添加和查找具有相同键的值。

QMultiHash<QString, int> multiHash;

multiHash.insert("key", 1);

multiHash.insert("key", 2);

QList<int> values = multiHash.values("key");

遍历: QHash 提供了多种遍历方式。可以使用 C++11 范围迭代(range-for loop)遍历 QHash,也可以使用迭代器(iterator)进行遍历。

for (const auto &key : hash.keys()) { ... }

for (const auto &value : hash.values()) { ... }

for (auto it = hash.begin(); it != hash.end(); ++it) { ... }

其他操作: QHash 提供了一些其他有用的操作,如交换(swap)、取差集(subtract)、合并(unite)等。

QHash<QString, int> hash1, hash2;

hash1.swap(hash2);

hash1.subtract(hash2);

hash1.unite(hash2);

(2)QHash示例

#include <QHash>
#include <QString>
#include <QDebug>// 自定义哈希函数,这里我们使用 Qt 提供的 qHash() 函数作为示例
uint qHash(const int &key, uint seed = 0) {return qHash(key, seed);
}// 自定义键相等操作,这里直接使用整数的相等操作
bool operator==(const int &key1, const int &key2) {return key1 == key2;
}int main() {// 1. 构造一个空的 QHashQHash<int, QString> hash;// 2. 插入键值对hash.insert(1, "one");hash.insert(2, "two");hash.insert(3, "three");// 3. 访问元素qDebug() << "Value for key 1:" << hash[1]; // 输出 "one"// 4. 修改元素hash[1] = "ONE";qDebug() << "Modified value for key 1:" << hash[1]; // 输出 "ONE"// 5. 检查元素是否存在if (hash.contains(3)) {qDebug() << "Key 3 is in the hash.";}// 6. 删除元素hash.remove(2);// 7. 获取键和值列表QList<int> keys = hash.keys();QList<QString> values = hash.values();// 8. 迭代 QHashQHash<int, QString>::iterator it;for (it = hash.begin(); it != hash.end(); ++it) {qDebug() << "Key:" << it.key() << "Value:" << it.value();}// 9. 从 QHash 提取一个值并删除该键值对QString value = hash.take(3);qDebug() << "Taken value for key 3:" << value; // 输出 "three"// 10. 检查 QHash 是否为空if (hash.isEmpty()) {qDebug() << "Hash is empty.";}// 11. 获取 QHash 的大小int size = hash.size();qDebug() << "Hash size:" << size; // 输出 2// 12. 清空 QHashhash.clear();if (hash.isEmpty()) {qDebug() << "Hash is now empty.";}// 13. 隐式共享QHash<int, QString> hash2;hash2 = hash; // hash 和 hash2 现在共享同一份数据if (hash.isSharedWith(hash2)) {qDebug() << "hash and hash2 are shared.";}return 0;
}

3.5 QMuItiHash

QMultiHash是QHash的子类,是用于处理多值映射的便利类,其用法与QMultiMap类似。与其它容器类(如QHash)相比,QMultiHash提供了一些额外的功能,如:

  • 容易处理具有相同键的数据:QMultiHash能够在一个键下存储多个值,使得管理这类数据变得简单高效。

  • 高性能:QMultiHash基于哈希表实现,因此查找、插入和删除操作的平均时间复杂度为O(1)。这意味着它在处理大量数据时仍然具有高性能。

  • 灵活的迭代器:QMultiHash提供了多种迭代器,例如const_iterator、iterator等,方便您遍历和操作容器中的数据。

  • 容易扩展和集成:QMultiHash作为Qt框架的一部分,与其他Qt类和功能有很好的兼容性。此外,QMultiHash的源代码可供查阅和修改,便于根据需求进行定制。

QMultiHash示例:

#include <QMultiHash>
#include <QList>
#include <QDebug>int main() {// 1. 创建一个 QMultiHashQMultiHash<QString, int> multiHash;// 2. 添加元素multiHash.insert("Alice", 25);multiHash.insert("Bob", 30);multiHash.insert("Alice", 28);multiHash.insert("Charlie", 23);// 3. 获取键值对数量qDebug() << "The multiHash has" << multiHash.count() << "key-value pairs.";// 4. 检查是否包含某个键if (multiHash.contains("Alice")) {qDebug() << "The multiHash contains the key 'Alice'.";}// 5. 获取某个键的值QList<int> aliceAges = multiHash.values("Alice");qDebug() << "Alice's ages are:" << aliceAges;// 6. 移除某个键值对multiHash.remove("Alice", 25);qDebug() << "After removing Alice's age 25, the multiHash contains" << multiHash.count() << "key-value pairs.";// 7. 使用迭代器遍历 QMultiHashqDebug() << "The multiHash contains the following key-value pairs:";for (auto it = multiHash.begin(); it != multiHash.end(); ++it) {qDebug() << it.key() << ":" << it.value();}// 8. 使用 C++11 范围遍历qDebug() << "The multiHash contains the following key-value pairs (using C++11 range-based loop):";for (const auto &pair : multiHash) {qDebug() << pair.first << ":" << pair.second;}// 9. 使用 uniqueKeys 获取去重后的键列表qDebug() << "The unique keys in the multiHash are:" << multiHash.uniqueKeys();// 10. 使用 keys 获取包含重复的键列表qDebug() << "All the keys in the multiHash are:" << multiHash.keys();// 11. 清空 QMultiHashmultiHash.clear();qDebug() << "After clearing, the multiHash has" << multiHash.count() << "key-value pairs.";return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/201242.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【labview报错,缺少GOOP Development Suite】

操作 当labview报此错误时&#xff0c;第一类情况为缺少包&#xff0c;第二类为所使用的GPU包已失效 以下为第一类缺包的解决方式 登录VIPM&#xff0c;如何安装VIPM查看此贴&#xff1a;VIPM安装 打开VIPM后&#xff0c;右上角输入goop,双击搜索出的安装包 勾选需要安装的包…

Linux部署Kettle(pentaho-server-ce-9.4.0.0-343)记录/配置MySQL存储

下载地址 Kettle 是一个开源的数据集成工具&#xff0c;它是 Pentaho Data Integration&#xff08;PDI&#xff09;项目的一部分。要访问 Kettle 的官方网站&#xff0c;可以通过访问其母公司 Hitachi Vantara 的网站来找到相关信息 官方网站&#xff1a;https://www.hitachi…

uni-app实现返回刷新上一页

方案一 通过监听器实现 page1 uni.$on("refresh", function(data) {if(data.page "page2") {this.reload()} })page2 methods: {handleBack() {uni.$emit("refresh", {page: "page2"})uni.navigateBack()} }方案二 通过页面实例实…

微信小程序:chooseimage从本地相册选择图片或使用相机拍照

文档 https://uniapp.dcloud.net.cn/api/media/image.html#chooseimage https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html 代码示例 const res await uni.chooseImage({count: 1, //默认9sizeType: [original, compressed], //可以…

浪潮信息KeyarchOS EDR 安全防护测评

背景 近几年服务器安全防护越来越受到企业的重视&#xff0c;企业在选购时不再仅仅看重成本&#xff0c;还更看重安全性&#xff0c;因为一旦数据泄露&#xff0c;被暴力破解&#xff0c;将对公司业务造成毁灭性打击。鉴于人们对服务器安全性的看重&#xff0c;本篇文章就来测…

【ArcGIS Pro】探索性插值无法覆盖所需shp范围

做个小记录自用&#xff0c;实际不准。 1 看看就行 pro插值 看看过程就行。有详细过程&#xff0c;类似tutorial https://learn.arcgis.com/zh-cn/projects/interpolate-temperatures-using-the-geostatistical-wizard/ 2 注意用投影坐标系 wgs84转投影坐标系 https://blog…

OSG编程指南<十八>:OSG读写保存文件及对中文字符的支持

基本几何体的绘制只适用于简单的编程&#xff0c;当场景中需要加载一个很复杂的模型时&#xff0c;还是需要从外部导入。osgDB 库 提供了读取二维图像和三维模型的接口&#xff0c;同时&#xff0c;也管理着第三方插件系统&#xff0c;以实现对不同格式文件的读取。 1、OSG 支…

在耳机心率血氧健康检测中应用的穿戴心率血氧接收芯片

时代快速发展的今天&#xff0c;随着生活节奏的加快&#xff0c;工作压力的加大&#xff0c;越来越多的消费者开始关注到自身身体健康&#xff0c;加班熬夜生活不规律&#xff0c;很容易让我们的身体处于亚健康的状态&#xff0c;而心率和体温的变化&#xff0c;就能反应我们身…

报表多源关联

报表多源关联 需求背景 在项目中会遇到多种数据展现在一起的报表。例如部分指标在关系型数据库中&#xff0c;部分指标通过restful接口获得到json&#xff0c;然后根据共同的维度关联一起&#xff0c;形成新的数据集。 解决方案 在硕迪报表中有两种方式实现该多源报表&…

生产环境_从数据到层级结构JSON:使用Spark构建多层次树形数据_父子关系生成

代码补充了&#xff01;兄弟萌 造的样例数据 val data Seq(("USA", "Male", "Asian", "Chinese"),("USA", "Female", "Asian", "Chinese"),("USA", "Male", "Bl…

SSL证书续签指南

SSL证书的有效期通常为一年&#xff0c;过期后将无法提供有效的加密保护&#xff0c;使网站容易受到黑客攻击和数据泄露的风险。所以SSL证书定期要进行续签&#xff0c;好确保网站的持久安全性。 首先我们要检查当前证书的有效期&#xff0c;打开网站&#xff0c;点击浏览器地址…

网络安全等级保护V2.0测评指标

网络安全等级保护&#xff08;等保V2.0&#xff09;测评指标&#xff1a; 1、物理和环境安全 2、网络和通信安全 3、设备和计算安全 4、应用和数据安全 5、安全策略和管理制度 6、安全管理机构和人员 7、安全建设管理 8、安全运维管理 软件全文档获取&#xff1a;点我获取 1、物…

TinyMPC - CMU (卡耐基梅隆大学)开源的机器人 MPC 控制器

系列文章目录 CasADi - 最优控制开源 Python/MATLAB 库 文章目录 系列文章目录前言一、机器人硬件对比1.1 Teensy 上的微控制器基准测试1.2 机器人硬件1.3 BibTeX 二、求解器三、功能&#xff08;预期&#xff09;3.1 高效3.2 鲁棒3.3 可嵌入式3.4 最小依赖性3.5 高效热启动3.…

手机怎么录屏?实用技巧,轻松录制!

手机录屏功能在现代通信和创作中扮演着重要的角色。无论是分享游戏过程、演示手机操作&#xff0c;还是创作教程视频&#xff0c;手机录屏成为了用户不可或缺的工具。本文将深入研究手机怎么录屏的三种方法&#xff0c;通过详细的步骤介绍&#xff0c;帮助用户轻松掌握手机录屏…

【无标题】从0到1 搭建一个vue3+Django项目

目录 一、后端项目python django二、前端项目vitevue3三、后端配置3.1 将路由指向app3.2 app下创建urls.py&#xff0c; 写入路由3.3 views写入test函数3.4 启动服务&#xff0c;访问路由 四、前端配置4.1 安装一些工具库及创建文件4.1.1 安装需要用的三方库4.1.2 创建文件 4.2…

Nacos 服务注册与发现

一、Spring Cloud Commons 二、使用方法 &#xff08;1&#xff09;在cloud-demo父工程中添加spring-cloud-alilbaba的管理依赖 &#xff08;2&#xff09;注释掉order-service和user-service中原有的eureka依赖 &#xff08;3&#xff09;添加nacos的客户端依赖 &#xff08;4…

Mysql学习查缺补漏----02 mysql之DCL 数据控制语言

查看数据库里都有哪些用户。 使用root任何一个用户都可以登录。 本机登录。 也可以这样登录其他的机器。 、 修改user表。 刷新权限&#xff1a; 现在我们看到了只有本机才能登陆。 我们这样就可以限制这个mysql指定某台服务器登录。 详解忘记密码以及如何修改用户密码 我们…

华为全面对标iOS,“纯血鸿蒙”时代来了

原创 | 文 BFT机器人 就在今年的10月份&#xff0c;华为官方宣布&#xff0c;鸿蒙OS 4升级设备数量已经突破1亿&#xff0c;成为史上升级最快的鸿蒙OS版本。 伴随着“Harmony OS NEXT”的启动&#xff0c;鸿蒙系统开发者社区迎来了喜讯——新增注册开发者数量已过万&#xff0…

C++ 命名空间详解

目录 引入例子 命名空间的定义 命名空间的使用 命名空间使用注意事项 引入例子 #include <stdio.h> #include <stdlib.h>int rand 10;int main() {printf("%d\n", rand);return 0; } 当我们用C语言写下这样的代码&#xff0c;看着并没有什么语法问…

AI助力智慧农业,基于YOLOv5全系列模型【n/s/m/l/x】开发构建不同参数量级农田场景下庄稼作物、杂草智能检测识别系统

紧接前文&#xff0c;本文是农田场景下庄稼作物、杂草检测识别的第二篇文章&#xff0c;前文是基于YOLOv3这一网络模型实现的目标检测&#xff0c;v3相对来说比较早期的网络模型了&#xff0c;本文是基于最为经典的YOLOv5来开发不同参数量级的检测端模型。 首先看下实例效果&a…