Qt學習總結(C魚)之QList和QMap容器類

QList<T>

QList<T>容器是一個數組列表,特點如下:

1.大多數情況下可以用QList。像prepend()、append()和insert()這種操作,通常QList比QVector快的多。這是因爲QList是基於index標籤存儲它的元素項在內存中(雖然內存不連續,這點與STL的list 是一樣的),比那種依賴iterator迭代的容器類更快捷,而且你的代碼也更少。

2.當迭代器指向QList中的一個項目後,如果QList進行了插入或者刪除操作,那麼這個迭代器就無效了。

3.QStringList類就是繼承QList<QString>容器類(注意QList<QString>其實是一個類模板,裏面裝的是QString類型,然後又有一個QStringList類繼承於它)。

QList<T>容器的簡單用法(由於QStringList是繼承於QList<String>,所以下面的所有用法對於QStringList容器一樣適用):

#include <QCoreApplication>
#include<QList>
#include<QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QList<QString> list;//創建了一個QList容器,容器內部存儲QString類型的數據,返回一個list對象,該對象有很多操作該容器的方法。
    list<<"aa"<<"bb"<<"cc";//可以採用<<的符號將數據輸入到容器內存儲。
    if(list[1]=="bb")
    {
        list[1]="ab";
    }
    list.replace(2,"bc");//list對象的replace方法將指定索引位置的元素值替換成指定的類型值,參數1是list索引位置,參數2是指定替換的類型值。
    qDebug()<<"the list is:";
    for(int i=0;i<list.size();++i)//list對象的size方法返回該容器存儲的元素個數。
    {
        qDebug()<<list.at(i);//list對象的at方法訪問容器內指定索引位置的元素值。
    }
    list.append("dd");//調用list對象的append函數進行尾插入指定類型值。
    list.prepend("mm");//調用list對象的prepend函數進行頭插入指定類型值。
    QString str=list.takeAt(2);//調用list對象的takeAt函數刪除指定索引值的元素並彈出該刪除的類型值。
    qDebug()<<"at(2) item is:"<<str;
    qDebug()<<"the list is:";
    for(int i=0;i<list.size();++i)//list對象的size方法返回該容器存儲的元素個數。
    {
        qDebug()<<list.at(i);//list對象的at方法訪問容器內指定索引位置的元素值。
    }
    list.insert(2,"mm");//調用list對象的insert方法在指定索引位置插入指定的類型值,參數1是索引值,參數2是要插入的類型值。
    list.swap(1,3);//調用list對象的swap方法交換指定兩個索引位置的元素值。
    qDebug()<<"the list is:";
    for(int i=0;i<list.size();++i)//list對象的size方法返回該容器存儲的元素個數。
    {
        qDebug()<<list.at(i);//list對象的at方法訪問容器內指定索引位置的元素值。
    }
    qDebug()<<"contains'mm'?"<<list.contains("mm");//判斷列表中是否包含“mm”
    qDebug()<<"the 'mm' count:"<<list.count("mm");//容器內包含“mm”的個數
    //第一個'mm'的位置,默認從0索引位置開始查找,找到就返回第一個匹配到的元素的索引位置
    qDebug()<<"the first 'mm' index:"<<list.indexOf("mm");
    //第二個'mm'的位置,我們指定從索引位置1開始查找
    qDebug()<<"the second 'mm' index:"<<list.indexOf("mm",1);
    return a.exec();
}

QMap<Key,T>

QMap<Key,T>容器是一個字典,屬於關聯容器的一種,特點如下:

1.它將Key類型的鍵值映射到T類型的值上,一般每個鍵關聯一個值,特殊情況出現於調用insertMulti函數插入多值。

2.並且它是根據鍵順序來存儲它的順序的。所以,QMap強調順序,那麼如果你存儲的數據不關心存儲順序,可以考慮使用QHash來代替它。

QMap<Key,T>容器的簡單用法():

#include <QCoreApplication>
#include<QMap>
#include<QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QMap<QString,int> map;//創建了一個QMap容器,容器內存儲的鍵是QString類型,值是int類型,一個鍵只對應一個值,並且存儲是講究鍵順序的。
    map["one"]=1;//當給一個容器內不存在的鍵賦值時,會自動將鍵和值添加進容器內
    map["three"]=3;
    map.insert("seven",7);//也可以使用insert來爲容器添加鍵值對。

    int value1=map["six"];//當採用鍵索引的方式訪問鍵的值時,若容器內無該鍵,那麼就會自動插入該新鍵,並且值默認設爲0。
    qDebug()<<"value1:"<<value1;
    qDebug()<<"contains'six'?"<<map.contains("six");

    int value2=map.value("five");//調用value函數,若指定要訪問的鍵在容器內找不到,那麼不會自動插入該新鍵,並且默認返回0,函數的參數2可以指定返回的值。
    qDebug()<<"value2:"<<value2;
    qDebug()<<"contains'five'?"<<map.contains("five");

    int value3=map.value("nine",9);//函數的參數2指定返回的值。
    qDebug()<<"value3:"<<value3;

    //map默認是一個鍵只對應存在一個值,所以,如果重新給該鍵設置了值,那麼以前的值就會被刪除替換,只保留最新的值。
    map.insert("ten",10);
    map.insert("ten",100);
    qDebug()<<"ten:"<<map.value("ten");

    /*
    map可以調用insertMulti函數來實現一鍵多值,值得注意的是,在QMap容器中,若存在某個鍵擁有多個值,那麼調用平常的value和
    使用map[鍵名]索引的方式訪問元素,那麼實際上返回的就是調用insertMulti函數最後一次添加的值,而values函數是專門提供給
    一鍵多值的元素用來返回這個元素的所有存在的值形成的列表,這個列表可以使用QList來保存起來。
    */
    map.insertMulti("two",2);
    map.insertMulti("two",4);
    QList<int> values=map.values("two");
    qDebug()<<"two:"<<values;

    //上面是QMap容器對象調用insertMulti函數實現一鍵多值,其實有專門的容器類實現一鍵多值的操作和存儲,例如:QMultimap
    //注意,這個QMultimap生成的一鍵多值對象和insertMulti函數實現的一鍵多值是有區別的,QMultimap對象不能夠索引方式訪問,但可以使用value函數來訪問多值中最新的那個值,還有values函數可以返回該鍵對應的所有值列表。
    QMultiMap<QString,int> map1,map2,map3;
    map1.insert("values",1);//插入values鍵,指定第一個值爲1
    map1.insert("values",2);//再次爲values鍵插入第二個值爲2
    map1.insert("qwe",888);//後面插入操作以此類推
    map1.insert("qwe",999);
    map2.insert("values",3);
    map2.insert("rty",444);

    map3=map1+map2;//相當於把map1對象內存儲的values和qwe鍵(不管鍵對應多值還是單值),還有map2對象存儲的values和rty鍵相合並然後全部放入到map3容器中。
    QList<int> myValues=map3.values("values");//QMultiMap容器類對象也跟QMap一樣擁有values函數來返回指定鍵的所有值的列表
    qDebug()<<"the values are:";
    for(int i=0;i<myValues.size();++i)
    {
        qDebug()<<myValues.at(i);
    }
    return a.exec();
}

遍歷容器(使用迭代器)

Qt容器類提供了兩種風格的迭代器,分別是JAVA風格迭代器和STL風格迭代器。JAVA風格迭代器有兩種數據類型,分別是隻讀迭代器和讀/寫迭代器。下面分別講解QList和QMap兩種容器類型的兩種迭代器。

QList容器的兩種迭代器

例如:

QList(容器類)->QListIterator(只讀迭代器)->QMutableListIterator(讀/寫迭代器)

QListIterator(注意,JAVA風格迭代器一直指向項目之間,不是直接指向項目)常用API:

  1. toFront():將迭代器移動到List列表的最前面(第一個項目之前)。
  2. toBack():將迭代器移動到List列表的最後面(最後一個項目之後)。
  3. hasNext():檢查該迭代器後面是否還有項目。
  4. next():迭代器向後移動,,返回它所跳過的項目。
  5. peekNext():迭代器不移動,返回它本來能跳過的項目。
  6. hasPrevious():檢查迭代器前面是否還有項目。
  7. previous:迭代器向前移動,返回它所跳過的項目。
  8. peekPrevious():迭代器不移動,返回它本來能跳過的項目。

上面的API,QMutableListIterator迭代器也都有,但由於QListIterator是隻讀迭代器,所以沒有提供插入和刪除項目的函數,而QMutableListIterator容器提供了insert和setValue函數來插入、設置值,remove函數來刪除項目。還有要注意的是QMutableListIterator容器雖然也有next和precious函數,但是與QListIterator迭代器有所不同,前者的這兩個函數返回的是非const引用,說明可以作爲左值進行賦值操作,而後者的兩個函數返回的是const引用,說明不能用來賦值操作,只能用於讀取,很符合這個只讀迭代器的定義。下面給出QMutableListIterator迭代器三個操作項目的函數用法:

insert(value):在迭代器指向的位置插入一個項目。

setValue(value):這個函數是將指定項目的值設置成指定的值,所以必須有個前提就是前面執行過next或者previous函數,其實意思就是這個函數對上一次跳過的項目進行賦值。

remove():刪除上一次跳過的項目。

案例代碼如下:

#include <QCoreApplication>
#include<QDebug>
#include<QList>
#include<QListIterator>
#include<QMutableListIterator>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QList<QString> list;//創建了一個QList容器對象
    list<<"A"<<"B"<<"C"<<"D";
    QListIterator<QString> i(list);//創建了一個指向QList的只讀迭代器,用list對象作爲參數
    qDebug()<<"the forward is:";
    while(i.hasNext())
        qDebug()<<i.next();
    qDebug()<<"the backward is:";
    while(i.hasPrevious())
        qDebug()<<i.previous();

    QMutableListIterator<QString> j(list);//創建了一個讀/寫迭代器
    j.toBack();
    while(j.hasPrevious()){
        QString str = j.previous();
        if(str=="B") j.remove();
    }
    /*
    要十分注意上面這個while循環,其實原本是ABCD列表(假如從左到右排列),然後刪除B後,因爲最後又多執行了一次循環內部代碼,所以迭代器就指向A的左側了。
    */
    j.insert("Q");
    j.toBack();
    if(j.hasPrevious()) j.previous()="N";
    j.previous();
    j.setValue("M");
    j.toFront();
    qDebug()<<"the forward is:";
    while(j.hasNext())
        qDebug()<<j.next();
    return a.exec();
}

QMap容器的兩種迭代器

例如:

QMap(容器類)->QMapIterator(只讀迭代器)->QMutableMapIterator(讀/寫迭代器)

與QListIterator迭代器類似,QMapIterator迭代器也提供了toFront()、toBack()、hasNext()、next()、peekNext()、hasPrevious()、previous()和peekPrevious()等函數。我們知道next()、peekNext()、previous()和peekPrevious()可以遍歷容器的內容,但仔細想想,前面QList還好,只有一個值,容易理解直接遍歷取值就行,但是QMap可是字典,含有鍵值對,那麼該怎樣遍歷獲取鍵和值呢?next()、peekNext()、previous()和peekPrevious()這四個函數不再返回引用,而是直接返回項目對象。可以在返回的這個項目對象上分別使用key()和value()函數來獲取鍵和值,也可以使用QMapIterator對象的key()和value()函數獲取鍵和值,下面會有案例說明兩者獲取方法的不同。
代碼如下:

#include <QCoreApplication>
#include<QDebug>
#include<QList>
#include<QListIterator>
#include<QMutableListIterator>
#include<QMap>
#include<QMapIterator>
#include<QMutableMapIterator>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QMap<QString,QString> map;
    map.insert("Paris","France");
    map.insert("Guatemala City","Guatemala");
    map.insert("Mexico City","Mexio");
    map.insert("Moscow","Russia");
    QMapIterator<QString,QString> i(map);//創建了一個只讀迭代器指向QMap對象
    while(i.hasNext()){
        i.next();
        /*
        注意,調用next函數後返回的是一個項目對象,可以使用這個項目對象的key()和value()方法獲取,
        例如:i.next().key()。但是對於這裏的需求是我們需要獲取鍵和值,如果連續兩次執行i.next().key()
        和i.next().value()那麼迭代器就移動兩次了,很明顯不符合我們的需求。其實當單獨執行了這個函數,迭代器也向後移
        動了一次,並且內部已經保存了跳過的
        項目的鍵和值,它告訴我們可以通過i對象的key()和
        value()函數獲取。就好像下面那條語句一樣。
        */
        qDebug()<<i.key()<<":"<<i.value();
    }
    qDebug()<<"--------------------";
    if(i.findPrevious("Mexico")) qDebug()<<"find 'Mexico'";
    QMutableMapIterator<QString,QString> j(map);
    while(j.hasNext()){
        //下面的j.next.key()語句可以看出,就是我們上面介紹的那樣,不過這裏的應用場景是爲了只單獨獲取鍵,然後匹配以City的項目後再刪除。
        if(j.next().key().endsWith("City"))
            j.remove();
    }
    while(j.hasPrevious()){
        j.previous();
        qDebug()<<j.key()<<":"<<j.value();
    }
    return a.exec();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章