学习QT之容器类

断了今生、忘了曾经 提交于 2020-03-01 12:27:17

学习QT之容器类


Qt提供了一组通用的基于模板的容器类。对比C++的标准模板库中的容器类,Qt的这些容器更轻量、更安全并且更容易使用。此外,Qt的容器类在速度、内存消耗和内联(inline)代码等方面进行了优化(较少的内联代码将说件可执行程序的大小)。

存储在Qt容器中的数据必须是可赋值的数据类型,也就是说,这种数据类型必须提供一个默认的构造函数、一个复制构造函数和一个赋值操作运算符。

这样的数据类型包含了通常使用的大多数数据类型,包括基本数据类型(如int和double等)和Qt的一些数据类型(如QString、QDate和QTime等)。不过,Qt的QObject及其他的子类(如QWidget和QDialog等)是不能存储在容器中的,例如:QList list;,一个可代替的方案是存储QObject及其子类的指针,例如:QList<QToolBar *> list。容器也可以嵌套使用,例如:QHash<QString,QList >; 注意容器类嵌套时后面的>之间一定要加一个空格,否则,C++编译器会将两个>符号解释为>>,导致无法通过编译器编译。

一、QList类、QLinkedList类和QVector类

1、QList类

QList是迄今为止最常用的容器类,它存储给定数据类型T的一列数值。继承自QList类的子类有QItemSelection、QQueue、QSigbalSpy、QStringList和QTestEventList。

函数 功能
append() 在尾部追加数据
prepend() 在头部追加数据
insert(pos, value) 在pos位置处插入value
#include<QDebug>
int main()
{
    QList<QString> list;  //初始化一个QList<QString>对象list
    {
        QString str("This is a string");
        list<<str;  //将字符串str加入list中
    }
    qDebug()<<list[0]<<"How are you! ";
    
    return 0;
}
2、QLinkedList类

QLinkedList是一个链式列表,它以非连续的内存块保存数据。

QLinkedList不能使用下标,只能使用迭代器访问它的数据项。与QList相比,当对一个很大的列表进行插入操作时,QLinkedList具有更高的效率。

3、QVector类

QVector在相邻的内存中存储给定数据类型T的一组数值。在一个QVector的前部或者中间位置进行插入操作的速度是很慢的,这因为这样的操作将导致内存中的大量数据被移动,这是由QVector存储数据的方式决定的。

QVector既可以使用下标访问数据项,也可以使用迭代器访问数据项。继承自QVector类的子类有QPolygon、QPolygonF和QStack。

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

Java风格迭代器同STL风格迭代器相比,使用起来更简单方便,不过这也是以轻微的性能损耗为代价的。对于每一个容器类,Qt提供了两种类的Java风格迭代器数据类型,即只读迭代器类和读写迭代器类。

容器类 只读迭代器类 读写迭代器类
QList,QQueue QListIterator QMutableListIterator
QLinkedList QLinkedListIterator QMutableLinkedListIterator
QVector,QStack QVectorIterator QMutableVectorIterator

Java风格迭代器的迭代的位于列表项的中间,而不是直接指向某个列表项。因此,它的迭代点或者在第一个列表项的前面,或者在两个列表项之间,或者在最后一个列表项之后。

(1)、QList只读迭代器遍历

方法 功能
hasNext() 检查当前迭代点之后是否有列表项
hasPrevious() 检查当前迭代点之前是否有列表项
toBack() 将迭代点移到最后一个列表项的后面
toFront() 将迭代点移动列表的最前端
next() 跳过下一个列表项,并返回它跳过的列表项的内容
peekNext() 返回下一个列表项,但不移动迭代点
peekPrevious() 返回前一个列表项,但不移动迭代点
findNext() 从当前迭代点开始向后查找指定的列表项,如果找到,则返回true,此时迭代点位于匹配列表项的后面;如果没有找到,则返回false,此时迭代点位于列表项的后端(最后一个列表项的后面)
findPrevious() 与findNext()类似,不同的是,它的方向是向前的,查找操作完成后的迭代点在匹配项的前面或整个列表的前端

实例代码

#include<QCoreApplication>
#include<QDebug>
int main(int argc,char *argv[])
{
    QCoreApplication a(argc,argv);
    QList<int> list;                        //创建一个空的列表list
    QListIterator<int> iter(list);          //创建一个上述列表的只读迭代器
    list<<1<<2<<3<<4;
    for(;iter.hasNext();)
    	qDebug()<<iter.next();

    return a.exec();
}

(2)、QList读写迭代器遍历

读写迭代器除了上述基本的遍历操作外,还提供了如下函数:

方法 功能
insert(value) 在列表中插入值value
remove() 在列表中移除数据
setValue(value) 在列表中设置数据

实例代码

#include<QCoreApplication>
#include<QDebug>
int main(int argc,char *argv[])
{
    QCoreApplication a(argc,argv);
    QList<int> list;                        //创建一个空的列表list
    QMutableListIterator<int> iter(list);          //创建一个上述列表的只读迭代器
    for(int i=0;i<10;i++)
		iter.insert(i);
    for(i.toFront;i.hasNext();)
		qDebug()<<iter.next();
    for(iter.toBack();iter.hasPrevious;)
    {
        if(iter.previous()%2==0)
            iter.remove();
        else
            iter.setValue(iter.peekNext()*10);
    }
    for(iter.toFront();iter.hasNext();)
		qDebug()<<iter.next();
    
    return a.exec();
}
5、STL风格迭代器遍历容器

对于每个容器类,Qt都提供了两种类型的STL风格迭代器数据类型:一种提供只读访问;另一种提供读写访问。由于只读类型的迭代器的运行速度要比读写迭代器的运行速度快,所以应尽可能地使用只读类型的迭代器。

STL风格迭代器的API是建立在指针操作基础上的。例如,“++”操作运算符移动迭代器到下一个项(item),而"*"操作运算符返回迭代器指向的项。

不同于Java风格迭代器,STL风格迭代器的迭代点直接指向列表项

容器类 只读迭代器 读写迭代器
QList,QQueue QList::const_iterator QList::iterator
QLinkedList QLinkedList::const_iterator QLinkedList::iterator
QVector,QStack QVector::const_iterator QVector::iterator
#include<QCoreApplication>
#include<QDebug>
int main(int argc,char *argv[])
{
    QCoreApplication a(argc,argv);
    QList<int> list;
    QList<int>::iterator iter;  //创建一个读写迭代器
    for(int i=0;i<10;i++)
        list.insert(list.end(),i);
    for(iter=list.begin();iter!=list.end();++iter)
    {
        qDebug()<<*iter;
        *iter=(*iter)*10;
    }
    
    QList<int>::const_iterator c_iter;  //创建一个只读迭代器
    for(c_iter=list.constBegin();c_iter!=list.constEnd();++c_iter)
        qDebug()<<*c_iter;
    
    return a.exec();
}

QLinkedList和QVector具有和QList相同的遍历接口,在此就不再详细讲解了。

二、QMap类和QHash类

QMap类和QHash类具有非常类似的功能,它们的差别仅在于:

  1. QHash具有比QMap更快的查找速度;
  2. QHash以任意的顺序存储数据项,而QMap总是按照键key的顺序存储数据;
  3. QHash的键类型key必须提供operator==()和一个全局的qHash(Key)函数,而QMap的键类型Key必须提供opeator<()函数。
1、QMap类

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

2、QHash类

QHash<Key,Value>具有和QMap几乎完全相同的API。QHash维护着一张哈希表,哈希表的大小与QHash的数据项的数目相适应。

QHash以任意顺序组织它的数据。当存储数据的顺序无关紧要是,建议使用QHash作为存放数据的容器。QHash也可以存储一键多值形式的数据,它的子类QMultiHash<Key,Value>实现了一键多值的语言。

3、Java风格迭代器遍历

对于每一个容器,Qt都提供了两种类型的Java风格迭代器数据类型:一种提供只读访问;另一种提供读写访问。

容器类 只读迭代器类 读写迭代器类
QMap<Key,Value>,QMultiMap<Key,Value> QMapIterator<Key,Value> QMutableMapIterator<Key,Value>
QHash<Key,Value>,QMultiHash<Key,Value> QHashIterator<Key,Value> QMutableHashIterator<Key,Value>

(1)、QMap只读迭代器遍历

方法 功能
hasNext() 检查是否有下一个列表项
next() 跳过下一个列表项,并访问该列表项
key() 访问键
value() 访问值
findValue(value) 寻找值
setValue(value) 设置值
insert(Key,Value) 插入键值对
#Include<QCoreApplication>
#Include<QDebug>
int main(int argc,char *argv)
{
    QCoreApplication a(argc,argv);
    QMap<QString,QString> map;
    map.insert("BeiJin","111");
    map.insert("ShangHai","021");
    map.insert("NanJin","025");
    QMapIterator<QString,QString> const_iter(map);
    for(;const_iter.hasNext();)
    {
        const_iter.next;
        qDebug()<<" "<<const_iter.key()<<" "<<const_iter.value();
    }
    QMutableMapIterator<QString,QString> iter(map);
    if(iter.findNext("111"))
        iter.setValue("101");
    for(;iter.hasNext();)
    {
        iter.next();
        qDebug()<<" "<<iter.key()<<" "iter.value();
    }
    
    return a.exec();
}

运行结果如下:

"BeiJin"    "111"
"NanJin"    "025"
"ShangHai"  "021"
"BeiJin"    "101"
"NanJin"    "025"
"ShangHai"  "021" 
4、STL风格迭代器遍历

对于每一个容器类,Qt都提供了两种类型的STL风格迭代器数据类型:一种提供只读访问;另一种提供读写访问。

容器类 只读迭代器类 读写迭代器类
QMap<Key,Value>,QMultiMap<Key,Value> QMap<Key,Value>::const_iterator QMap<Key,Value>::iterator
QHash<Key,Value>,QMultiHash<Key,Value> QHash<Key,Value>::const_iterator QHash<Key,Value>::iterator
#include<QCoreApplication>
#Include<QDebug>
int main(int argc,char *argv)
{
    QCoreApplication a(argc,argv);
    QMap<QString,QString> map;
    map.insert("BeiJin","111");
    map.insert("ShangHai","021");
    map.insert("NanJin","025");
    QMap<QString,QString>::const_iterator const_iter;
    for(const_iter=map.constBegin();const_iter!=map.constEnd();++const_iter)
        qDebug()<<" "<<const_iter.key()<<" "<<const_iter.value();
    QMap<QString,QString>::iterator iter;
    iter=map.find("BeiJin");
    if(iter!=map.end())
        iter.value()="010";
    QMap<QString,QString>::const_iterator modi;
    for(modi=map.constBegin();modi!=map.constEnd();++modi)
        qDebug()<<" "<<modi.key()<<" "modi.value();
    
    return a.exec();
}

运行结果如下:

"BeiJin"    "111"
"NanJin"    "025"
"ShangHai"  "021"
"BeiJin"    "101"
"NanJin"    "025"
"ShangHai"  "021" 

三、QVariant类

QVariant类类似于C++的联合(union)数据类型,它不仅能保存很多Qt类型的值,包括QCore、QBrush、QFont、QPen、QString和QSize等,而且也能存放Qt的容器类型的值。Qt的很多功能都是建立在QVariant基础上的,如Qt的对象属性即数据库功能等。

#include"widget.h"
#include<QDebug>
#include<QVariant>
#include<QColor>
Widget::Wideget(QWidget *parent)
    : QWidget(parent)
{
    QVariant v(709);         //声明一个QVariant变量,并初始化为一个整数
    qDebug()<<v.toInt();
    QVariant w("How are you! ");     //声明一个QVariant变量,并初始化为一个字符串
    qDebug()<<w.toString;
    QMap<QString,QVariant> map;
    map["int"]=709;
    map["double"]=709.709;
    map["string"]="How are you! ";
    map["color"]=QColor(255,0,0);
    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 s1;
    s1<<"A"<<"B"<<"C"<<"D";
    QVariant slv(s1);
    if(slv.type==QVariant.toStringList)
    {
        QStringList list=slv.toStringList();
        for(int i=0;i<list.size();++i)
            qDebug()<<list.at(i);
    }
}

说明:QVariant::type()函数返回存储在QVariant变量中的值的数据类型。QVariant::StringList是Qt定义的一个QVariant::type枚举类型的变量。Qt的常用QVariant::type枚举类型变量如下:

变量 对应的类型 变量 对应的类型
QVariant::Invaild 无效类型 QVariant::Time QTime
QVariant::Region QRegion QVariant::Line QLine
QVariant::Bitmap QBitmap QVariant::Palette QPalette
QVariant::Bool bool QVariant::List QList
QVariant::Brush QBrush QVariant::SizePolicy QSizePolicy
QVariant::Size QSize QVariant::String QString
QVariant::Char QChar QVariant::Map QMap
QVariant::Color QColor QVariant::StringList QStringList
QVariant::Cursor QCursor QVariant::Point QPoint
QVariant::Date QDate QVariant::Pen QPen
QVariant::DateTime QDateTime QVariant::Pixmap QPixmap
QVariant::Double double QVariant::Rect QRect
QVariant::Font QFont QVariant::Image QInage
QVariant::Icon QIcon QVariant::UserType 用户自定义类型

运行结果如下:

709
"How are you! "
QVariant(int 709) 709
QVariant(double,709.709) 709.709
QVariant(QString,"How are you! ") "How are you! "
QVariant(QColor,QColor(ARGB 1,1,0,0)) QColor(ARGB 1,1,0,0)
"A"
"B"
"C"
"D"
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!