学习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"