一、Qt容器的遍历器

Qt 的容器类提供了两种风格的遍历器:Java 风格和 STL 风格。

每一种容器都有两种 Java 风格的遍历器:一种提供只读访问,一种提供读写访问:

容器

只读遍历器

读写遍历器

QList<T>,QQueue<T>

QListIterator<T>

QMutableListIterator<T>

QLinkedList<T>

QLinkedListIterator<T>

QMutableLinkedListIterator<T>

QVector<T>,QStack<T>

QVectorIterator<T>

QMutableVectorIterator<T>

QSet<T>

QSetIterator<T>

QMutableSetIterator<Key,T>

QMap<Key, T>,QMultiMap<Key, T>

QMapIterator<Key,T>

QMutableMapIterator<Key,T>

QHash<Key, T>,QMultiHash<Key, T>

QHashIterator<Key,T>

QMutableHashIterator<Key,T>

 

STL 风格的遍历器

STL 风格的遍历器从 Qt 2.0 就开始提供。这种遍历器能够兼容 Qt 和 STL 的通用算法,并且为速度进行了优化。同 Java 风格遍历器类似,Qt 也提供了两种 STL 风格的遍历器:一种是只读访问,一种是读写访问。我们推荐尽可能使用只读访问,因为它们要比读写访问的遍历器快一些。

容器

只读遍历器

读写遍历器

QList<T>,QQueue<T>

QList<T>::const_iterator

QList<T>::iterator

QLinkedList<T>

QLinkedList<T>::const_iterator

QLinkedList<T>::iterator

QVector<T>,QStack<T>

QVector<T>::const_iterator

QVector<T>::iterator

QSet<T>

QSet<T>::const_iterator

QSet<T>::iterator

QMap<Key, T>,QMultiMap<Key, T>

QMap<Key, T>::const_iterator

QMap<Key, T>::iterator

QHash<Key, T>,QMultiHash<Key, T>

QHash<Key, T>::const_iterator

QHash<Key, T>::iter

二、QMap和QHash的对比分析

QMap和QHash的接口相同,可直接替换使用,它们之间的差异如下:

(1)、QHash的查找速度明显快于QMap

(2)、QHash占用的存储空间明显多于QMap

(3)、QHash以任意的方式存储元素

(4)、QMap以Key顺序存储元素

(5)、QHash如果使用自定义类型作为主键,QHash的键类型必须提供operator == () 和 qHash(key)函数

(6)、QMap如果使用自定义类型作为主键,QMap的键类型必须提供operator <函数

 

三、使用实例

#include "mainwindow.h"
#include <QApplication>
#include <QMap>
#include <QHash>
#include <QDate>
#include <QDebug>

struct Student
{
    QString name;
    int no;

    bool operator <(const struct Student& other) const
    {
        if (name < other.name)
        {
            return true;
        }
        else if (name == other.name)
        {
            return no < other.no;
        }

        return false;
    }
};

class Employee
{
public:
    Employee() {}
    Employee(const QString &name, const QDate &dateOfBirth){myName = name;myDateOfBirth = dateOfBirth;}
    const QString name(){return myName;}
    const QDate dateOfBirth(){return myDateOfBirth;}

    inline bool operator==(const Employee &other) const
    {
        return (myName==other.myName && myDateOfBirth==other.myDateOfBirth);
    }
    //以下的写法是错误的//error: passing 'const Employee' as 'this' argument of 'const QString Employee::name()' discards qualifiers
    /*inline bool operator==(const Employee &other) const
    {
        return myName == other.name()
               && myDateOfBirth == other.dateOfBirth();
    }*/

public:
    QString myName;
    QDate myDateOfBirth;
};

//以下的写法是错误的://error: passing 'const Employee' as 'this' argument of 'const QString Employee::name()' discards qualifiers
/*inline uint qHash(const Employee &key)
{
    return qHash(key.name()) ^ key.dateOfBirth().day();
}*/

inline uint qHash(const Employee key)
{
    //^ -----按位异或(Xor)是一种可逆运算符,只有在两个比较的位不同时其结果是1,否则结果为0。
    return qHash(key.myName) ^ key.myDateOfBirth.day();
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //----------------Java 风格的遍历器
    /*每一种容器都有两种 Java 风格的遍历器:一种提供只读访问,一种提供读写访问:
    容器                                 只读遍历器                读写遍历器
    QList<T>,QQueue<T>                  QListIterator<T>        QMutableListIterator<T>
    QLinkedList<T>                      QLinkedListIterator<T>  QMutableLinkedListIterator<T>
    QVector<T>,QStack<T>                QVectorIterator<T>      QMutableVectorIterator<T>
    QSet<T>                             QSetIterator<T>         QMutableSetIterator<T>
    QMap<Key, T>,QMultiMap<Key, T>      QMapIterator<T>         QMutableMapIterator<T>
    QHash<Key, T>,QMultiHash<Key, T>    QHashIterator<T>        QMutableHashIterator<T>
    */
    //----------------end Java 风格的遍历器
    //------QMap
    QMap<int,QString> id2NameMap;
    id2NameMap.insert(2,"name2");
    id2NameMap.insert(1,"name1");
    id2NameMap.insert(3,"name3");
    qDebug()<<id2NameMap;
    //只读遍历器
    QMapIterator<int,QString> it1(id2NameMap);
    while (it1.hasNext())
    {
        it1.next();
        if(2 == it1.key())
        {
            qDebug() << it1.value();
        }
    }

    //读写遍历器
    QMutableMapIterator<int,QString> mit1(id2NameMap);
    while (mit1.hasNext())
    {
        mit1.next();
        if(2 == mit1.key())
        {
            mit1.setValue("name2new");
            qDebug() << mit1.value();
        }
    }
    qDebug()<<id2NameMap;
    //------end QMap

    //----------------STL 风格的遍历器
    /*STL 风格的遍历器从 Qt 2.0 就开始提供。这种遍历器能够兼容 Qt 和 STL 的通用算法,并且为速度进行了优化。
     * 同 Java 风格遍历器类似,Qt 也提供了两种 STL 风格的遍历器:一种是只读访问,一种是读写访问。
     * 我们推荐尽可能使用只读访问,因为它们要比读写访问的遍历器快一些。

    容器                                 只读遍历器                        读写遍历器
    QList<T>,QQueue<T>                  QList<T>::const_iterator        QList<T>::iterator
    QLinkedList<T>                      QLinkedList<T>::const_iterator  QLinkedList<T>::iterator
    QVector<T>,QStack<T>                QVector<T>::const_iterator      QVector<T>::iterator
    QSet<T>                             QSet<T>::const_iterator         QSet<T>::iterator
    QMap<Key, T>,QMultiMap<Key, T>      QMap<Key, T>::const_iterator    QMap<Key, T>::iterator
    QHash<Key, T>,QMultiHash<Key, T>    QHash<Key, T>::const_iterator   QHash<Key, T>::iter
     */

    //------QHash
    QHash<int,QString> id2NameHash;
    id2NameHash.insert(2,"hashName2");
    id2NameHash.insert(1,"hashName1");
    id2NameHash.insert(3,"hashName3");
    qDebug()<<id2NameHash;
    //只读遍历器
    QHash<int,QString>::const_iterator rIt1;
    for (rIt1 = id2NameHash.begin(); rIt1 != id2NameHash.end(); ++rIt1)
    {
        if(2 == rIt1.key())
        {
            qDebug() << rIt1.value();
        }
    }
    //读写遍历器
    QHash<int,QString>::iterator wIt1;
    for (wIt1 = id2NameHash.begin(); wIt1 != id2NameHash.end(); ++wIt1)
    {
        if(2 == wIt1.key())
        {
            //修改内容
            *wIt1 = "hashName2new";// 使用 * 运算符获取遍历器所指的元素
            qDebug() << wIt1.value();
        }
        else if(3 == wIt1.key())
        {
            //修改内容
            id2NameHash.insert(3,"hashName3new");
            qDebug() << wIt1.value();
        }
    }
    qDebug()<<id2NameHash;
    //------end QHash

    //----------------------自定义key类型
    //QHash的键类型必须提供operator == () 和 qHash(key)函数
    //QMap的键类型必须提供operator <

    //------自定义 QMap的Key类型
    QMap<Student,QString> key2NameMap;
    Student tmp;
    tmp.no = 2;
    tmp.name = "name2";
    key2NameMap.insert(tmp,"name2");
    tmp.no = 1;
    tmp.name = "name1";
    key2NameMap.insert(tmp,"name1");
    tmp.no = 3;
    tmp.name = "name3";
    key2NameMap.insert(tmp,"name3");
//    qDebug()<<key2NameMap;

    Student find;
    find.no = 2;
    find.name = "name2";
    QMap<Student,QString>::iterator cusIt1 = key2NameMap.find(find);
    if(cusIt1 != key2NameMap.end())
    {
        qDebug()<<"I can find";
    }
    else
    {
        qDebug()<<"I can not find";
    }
    //------end 自定义 QMap的Key类型

    //------自定义 QHash的Key类型
    QHash<Employee,QString> customHash;
    customHash.insert(Employee("name1", QDate(2018,10,21)),"name1");
    customHash.insert(Employee("name3", QDate(2018,10,23)),"name3");
    customHash.insert(Employee("name2", QDate(2018,10,22)),"name2");
    customHash.insert(Employee("name7", QDate(2018,10,27)),"name7");
    //只读遍历器
    QHash<Employee,QString>::const_iterator rIt2;
    for (rIt2 = customHash.begin(); rIt2 != customHash.end(); ++rIt2)
    {
        qDebug() << rIt2.key().myName << ":" << rIt2.value();
    }
    //------end 自定义 QHash的Key类型


    MainWindow w;
    w.show();

    return a.exec();
}

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐