QT学习:容器类及QVariant类

Qt提供了一组通用的基 于模板的容器类。对比C++的标准模板库中的容器类,Qt 的这些容器更轻量、更安全并且更容易使用。
存储在Qt容器中的数据必须是可赋值的数据类型,也就是说,这种数据类型必须提供一个默认的构造函数(不需要参数的构造函数)、一个复制构造函数和一个赋值操作运算符。
这样的数据类型包含了通常使用的大多数数据类型,包括基本数据类型(如int和double等)和Qt的一些数据类型(如QString、 QDate和QTime等)。不过,Qt的QObject及其他的子类(如QWidget和Qdialog等)是不能够存储在容器中的,一个可代替的方案是存储QObject及其子类的指针。
此外Qt的容器类也是可以嵌套的。
Qt的容器类位遍历其中的内容提供了两种方法,一种是Java风格的迭代器,另一种是STL风格的迭代器。

一、QList类、QLinkedList类、QVector类

下图为这三个类的时间复杂度比较:
在这里插入图片描述

1、QList类

QList<T>是迄今为止最常用的容器类,它存储给定数据类型T的一列数值。 继承自QList类的子类有QltemSelection.、QQueue、 QSigalspy、 QStringList 和QTestEventList。
常用的函数有:
QList::append()、QList::prepend():在列表中进行追加。
QList::insert()函数:在列表中进行插入。
QList<T>维护了一个指针数组,该数组存储的指针指QList<T>存储的列表项的内容。因此,QList<T>提供了基于下标的快速访问。
对于不同的数据类型,QList<T> 采取不同的存储策略,存储策略有以下几种。
(1)如果T是一个指针类型或指针大小的基本类型,QList<T> 会将数值直接存储在它的数组中。
(2)如果QList<T>存储对象的指针。则该指针指向实际存储的对象。

2、QLinkedList类

QLinkedList<T>是一个链式列表,它以非连续的内存块保存数据。
QLinkedList<T>不能使用下标,只能使用迭代器访问它的数据项。与QList相比,当对一个很大的列表进行插入操作时,QLinkedList 具有更高的效率。

3、QVector类

QVector<T>在相邻的内存中存储给定数据类型T的一组数值。在一个QVector的前部或者中间位置进行插入操作的速度是很慢的,这是因为这样的操作将导致内存中的大量数据被移动,这是由QVector存储数据的方式决定的。
QVector<T>既可以使用下标访问数据项,也可以使用迭代器访问数据项。继承自QVector类的子类有QPolygon、QPolygonF 和QStack。

4、Java风格迭代器遍历容器

下图是两种类型的 Java风格迭代器数据类型
在这里插入图片描述
Java风格迭代器的迭代点 位于列表项的中间,而不是直接指向某个列表项。因此,它的迭代点或者在第一个列表项的前面,或者在两个列表项之间,或者在最后一个列表项之后。
下面以QList为例,介绍两种Java风格迭代器的用法。QLinkedlist 和QVector具有与QList相同的遍历接口,在此不再详细讲解。
(1) QList只读遍历方法。

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QList<int> list;
    list<<1<<2<<3<<4<<5;
    QListIterator<int> i(list);
    for(;i.hasNext();)
        qDebug()<<i.next();
    return a.exec();
}

以上是对列表进行前向遍历,后向遍历的函数有:
QListIterator<T>::toBack():将迭代点移动到最后一个列表项的后面。
QListIterator<T>::hasPrevious():检查当前迭代点之前是否具有列表项。
QListIterator<T>::Previous():返回前个列表项的内容并将迭代点移动到前一个列表项之前。
(2) QListIterator<T> 是只读迭代器,它不能完成列表项的插入和删除操作。读写迭代器QMutableListIterator<T>除提供基本的遍历操作外,还提供了insert()插入,remove()删除操作函数和修改数据函数等。
以下代码为QList读写操作:

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QList<int> list;
    QMutableListIterator<int> i(list);
    for(int j=0;j<10;++j)
        i.insert(j);
    for(i.toFront();i.hasNext();)
        qDebug()<<i.next();
    for(i.toBack();i.hasPrevious();)
    {
        if(i.previous()%2==0)
            i.remove();
        else
            i.setValue(i.peekNext()*10);
    }
    for(i.toFront();i.hasNext();)
        qDebug()<<i.next();
    return a.exec();
}

5、STL风格迭代器遍历容器

STL风格迭代器的两种分类如下图所示:
在这里插入图片描述

二、QMap类和QHash类

QMap类和QHash类具有非常类似的功能,它们的差别仅在于:
QHash具有比QMap更快的查找速度;
QHash以任意的顺序存储数据项,而QMap总是按照键(Key的顺序存储数据;
QHash的键类型Key必须提供operator==()和一个全局的qHash(Key)函数,而QMap的键类型Key必须提供operator<()函数。
QMap和QHash的时间复杂图如图:
在这里插入图片描述

1、QMap类

QMap<Key,T>提供了一个从类型为 Key的键到类型为T的值的映射。
通常,QMap存储的数据形式是一个键对应一个值,并且按照键Key的顺序存储数据。为了能够支持一键多值的情况,QMap提供了QMaps<Key,T>::insertMulti()和QMap<Key,T>::values()函数。存储一键多值的数据时,也可以使用QMultiMap<Key,T>容器,它继承自QMap。

2、QHash 类

QHash<Key,T>具有与QMap几乎完全相同的API。QHash维护着一张哈希表( Hash Table),哈希表的大小与QHash的数据项的数目相适应。
QHash以任意的顺序组织它的数据。当存储数据的顺序无关紧要时,建议使用QHash作为存放数据的容器。QHash也可以存储一键多值形式的数据,它的子类QMultiHash<Key,T>实现了一键多值的语义。

3. Java 风格迭代器遍历容器

Java风格迭代器的两种分类如下图所示:
在这里插入图片描述
下面举一个例子,包含在QMap中的插入、遍历和修改,如下代码:

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QMap<QString,QString> map;					//创建一个QMap栈对象
    //向栈对象插入<城市,区号>对
    map.insert("beijing","111");
    map.insert("shanghai","021");
    map.insert("nanjing","025");
    QMapIterator<QString,QString> i(map);		//创建一个只读迭代器
    for(;i.hasNext();)							
        qDebug()<<"  "<<i.key()<<"  "<<i.next().value();
    QMutableMapIterator<QString,QString> mi(map);
    if(mi.findNext("111"))						
        mi.setValue("010");
    QMapIterator<QString,QString> modi(map);
    qDebug()<<"  ";
    for(;modi.hasNext();)						//再次遍历并输出修改后的结果
        qDebug()<<" "<<modi.key()<<"  "<<modi.next().value();

    return a.exec();
}

4、STL风格迭代器遍历容器

STL风格迭代器的两种分类如下图所示:
在这里插入图片描述

三、QVariant类

QVariant类类似于C++的联合(union) 数据类型,它不仅能保存很多Qt 类型的值,包括QColor、QBrush、 QFont、QPen、QRect、QString 和QSize等,而且也能存放Qt的容器类型的值。Qt的很多功能都是建立在QVariant基础上的,如Qt的对象属性及数据库功能等。
下面我们用一个例子介绍这个类的具体用法:

#include "widget.h"
#include <QDebug>
#include <QVariant>
#include <QColor>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QVariant v(709);					//声明QVariant变量v
    qDebug()<<v.toInt();				//将变量包含的内容转换为整数并输出
    QVariant w("How are you! ");		//声明一个QVariant变量w
    qDebug()<<w.toString();				//将w包含的内容转换为字符串并输出
    QMap<QString,QVariant>map;			
    map["int"]=709;						//输入整数型
    map["double"]=709.709;				//输入浮点型
    map["string"]="How are you! ";		//输入字符串
    map["color"]=QColor(255,0,0);		//输入QColor类型的值
    //调用相应的转换函数并输出
    qDebug()<<map["int"]<< map["int"].toInt();
    qDebug()<<map["double"]<< map["double"].toDouble();
    qDebug()<<map["string"]<< map["string"].toString();
    qDebug()<<map["color"]<< map["color"].value<QColor>();	
    QStringList sl;						//创建一个字符串列表
    sl<<"A"<<"B"<<"C"<<"D";
    QVariant slv(sl);					//将该列表保存在一个QVariant变量中
    if(slv.type()==QVariant::StringList)
    {
        QStringList list=slv.toStringList();
        for(int i=0;i<list.size();++i)
            qDebug()<<list.at(i);		//输出列表内容
    }

}

Widget::~Widget()
{

}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值