# Qt5 中的容器

> 原文： [http://zetcode.com/gui/qt5/containers/](http://zetcode.com/gui/qt5/containers/)

在 Qt5 教程的这一部分中，我们将讨论 Qt5 中的容器。 提及以下容器：`QVector`，`QList`，`QStringList`，`QSet`和`QMap`。

容器是通用类，用于将给定类型的项目存储在内存中。 C++ 具有标准模板库（STL），该模板库具有自己的容器。 对于 Qt，我们可以使用 Qt 容器或 STL 容器。

有两种容器：顺序容器和关联容器。 顺序容器一个接一个地存储项目，而关联容器存储键值对。 `QList`，`QVector`，`QLinkedList`属于顺序容器； `QMap`和`QHash`是关联容器的示例。

## `QVector`

`QVector`是提供动态数组的模板类。 它将项目存储在相邻的内存位置，并提供基于索引的快速访问。 对于大向量，插入操作较慢，建议改用`QList`容器。

`myvector.cpp`

```cpp
#include <QVector>
#include <QTextStream>

int main(void) {

    QTextStream out(stdout);

    QVector<int> vals = {1, 2, 3, 4, 5};

    out << "The size of the vector is: " << vals.size() << endl;

    out << "The first item is: " << vals.first() << endl;
    out << "The last item is: " << vals.last() << endl;

    vals.append(6);
    vals.prepend(0);   

    out << "Elements: "; 

    for (int val : vals) {
        out << val << " ";
    }    

    out << endl;

    return 0;
}

```

该示例使用整数向量。

```cpp
QVector<int> vals = {1, 2, 3, 4, 5};

```

创建一个整数向量。

```cpp
out << "The size of the vector is: " << vals.size() << endl;

```

`size()`方法给出向量的大小-向量中的项数。

```cpp
out << "The first item is: " << vals.first() << endl;

```

使用`first()`方法检索第一项。

```cpp
out << "The last item is: " << vals.last() << endl;

```

使用`last()`方法可以找到向量的最后一项。

```cpp
vals.append(6);

```

`append()`方法将值插入向量的末尾。

```cpp
vals.prepend(0);

```

`prepend()`方法将值插入向量的开头。

```cpp
for (int val : vals) {
    out << val << " ";
}    

```

我们遍历`for`循环中的向量并打印其内容。

输出：

```cpp
$ ./myvector 
The size of the vector is: 5
The first item is: 1
The last item is: 5
Elements: 0 1 2 3 4 5 6 

```

## `QList`

`QList`是用于创建元素列表的容器。 与`QVector`相似。 它存储值列表，并提供基于索引的快速访问以及快速插入和删除。 它是 Qt 中最常用的容器之一。

`mylist.cpp`

```cpp
#include <QTextStream>
#include <QList>
#include <algorithm>

int main(void) {

    QTextStream out(stdout);

    QList<QString> authors = {"Balzac", "Tolstoy", 
        "Gulbranssen", "London"};

    for (int i=0; i < authors.size(); ++i) {

        out << authors.at(i) << endl;
    }  

    authors << "Galsworthy" << "Sienkiewicz";

    out << "***********************" << endl;

    std::sort(authors.begin(), authors.end());

    out << "Sorted:" << endl;
    for (QString author : authors) {

        out << author << endl;
    }  
}

```

该示例介绍了`QList`容器。

```cpp
QList<QString> authors = {"Balzac", "Tolstoy", 
    "Gulbranssen", "London"};

```

创建一个`QList`容器。 它存储作家的姓名。

```cpp
for (int i=0; i < authors.size(); ++i) {

    out << authors.at(i) << endl;
}  

```

在`for`循环中，我们遍历容器并打印其元素。 `at()`方法返回给定索引处的项目。

```cpp
authors << "Galsworthy" << "Sienkiewicz";

```

`<<`运算符用于在列表中插入两个新项目。

```cpp
std::sort(authors.begin(), authors.end());

```

`std::sort()`方法按升序对列表进行排序。

```cpp
out << "Sorted:" << endl;
for (QString author : authors) {

    out << author << endl;
} 

```

现在我们打印排序列表。

输出：

```cpp
$ ./mylist 
Balzac
Tolstoy
Gulbranssen
London
***********************
Sorted:
Balzac
Galsworthy
Gulbranssen
London
Sienkiewicz
Tolstoy

```

## `QStringList`

`QStringList`是提供字符串列表的便捷容器。 它具有基于索引的快速访问以及快速的插入和删除。

`mystringlist.cpp`

```cpp
#include <QTextStream>
#include <QList>

int main(void) {

    QTextStream out(stdout);

    QString string = "coin, book, cup, pencil, clock, bookmark";
    QStringList items = string.split(",");
    QStringListIterator it(items);

    while (it.hasNext()) {
        out << it.next().trimmed() << endl;    
    }
}

```

在示例中，我们从一个字符串创建一个字符串列表，并将元素打印到控制台中。

```cpp
QString string = "coin, book, cup, pencil, clock, bookmark";
QStringList items = string.split(",");

```

`QString`的`split()`方法根据提供的分隔符将字符串切成子字符串。 子字符串在列表中返回。

```cpp
QStringListIterator it(items);

```

`QStringListIterator`为`QStringList`提供了 Java 样式的常迭代器。

```cpp
while (it.hasNext()) {
    out << it.next().trimmed() << endl;    
}

```

使用创建的迭代器，我们将列表的元素打印到终端。 `trimmed()`方法可修剪字符串元素中的空白。

输出：

```cpp
$ ./mystringlist 
coin
book
cup
pencil
clock
bookmark

```

## `QSet`

`QSet`提供具有快速查找功能的单值数学集。 值以未指定的顺序存储。

`myset.cpp`

```cpp
#include <QSet>
#include <QList>
#include <QTextStream>
#include <algorithm>

int main(void) {

    QTextStream out(stdout);

    QSet<QString> cols1 = {"yellow", "red", "blue"};
    QSet<QString> cols2 = {"blue", "pink", "orange"};

    out << "There are " << cols1.size() << " values in the set" << endl;

    cols1.insert("brown");

    out << "There are " << cols1.size() << " values in the set" << endl;

    cols1.unite(cols2);

    out << "There are " << cols1.size() << " values in the set" << endl;

    for (QString val : cols1) {
        out << val << endl;
    }

    QList<QString> lcols = cols1.values();
    std::sort(lcols.begin(), lcols.end());

    out << "*********************" << endl;
    out << "Sorted:" << endl;

    for (QString val : lcols) {
        out << val << endl;
    }    

   return 0;
}

```

在示例中，`QSet`用于存储颜色。 多次指定一种颜色值没有意义。

```cpp
QSet<QString> cols1 = {"yellow", "red", "blue"};
QSet<QString> cols2 = {"blue", "pink", "orange"};

```

我们有两组颜色值。 两组中都有蓝色。

```cpp
out << "There are " << cols1.size() << " values in the set" << endl;

```

`size()`方法返回集合的大小。

```cpp
cols1.insert("brown");

```

我们使用`insert()`方法向集合中添加新值。

```cpp
cols1.unite(cols2);

```

`unite((`方法执行两个集合的并集。 `cols1`设置将具有从`cols2`设置插入的所有尚不存在的项目。 在我们的案例中，除了蓝色以外的所有颜色。

```cpp
for (QString val : cols1) {
    out << val << endl;
}

```

使用`for`循环，我们打印`cols1`集中的所有项目。

```cpp
QList<QString> lcols = cols1.values();
std::sort(lcols.begin(), lcols.end());

```

不支持对集合进行排序。 我们可以创建一个列表并对其进行排序。 `values()`方法返回一个新的`QList`，其中包含集合中的元素。 `QList`中元素的顺序未定义。

输出：

```cpp
$ ./myset 
There are 3 values in the set
There are 4 values in the set
There are 6 values in the set
pink
orange
brown
blue
yellow
red
*********************
Sorted:
blue
brown
orange
pink
red
yellow

```

## `QMap`

`QMap`是一个存储键值对的关联数组（字典）。 它提供与键关联的值的快速查找。

`myqmap.cpp`

```cpp
#include <QTextStream>
#include <QMap>

int main(void) {

    QTextStream out(stdout);

    QMap<QString, int> items = { {"coins", 5}, {"books", 3} };

    items.insert("bottles", 7);

    QList<int> values = items.values();

    out << "Values:" << endl;

    for (int val : values) {
        out << val << endl;
    }

    QList<QString> keys = items.keys();

    out << "Keys:" << endl;
    for (QString key : keys) {
        out << key << endl;
    }    

    QMapIterator<QString, int> it(items);

    out << "Pairs:" << endl;

    while (it.hasNext()) {
        it.next();
        out << it.key() << ": " << it.value() << endl;    
    }
}

```

在示例中，我们有一个字典，在其中将字符串键映射到整数值。

```cpp
QMap<QString, int> items = { {"coins", 5}, {"books", 3} };

```

创建了`QMap`。 它有两对。

```cpp
items.insert("bottles", 7);

```

使用`insert()`方法插入一对新的对。

```cpp
QList<int> values = items.values();

out << "Values:" << endl;

for (int val : values) {
    out << val << endl;
}

```

我们获取字典的所有值并将其打印到控制台。 `values()`方法返回映射值列表。

```cpp
QList<QString> keys = items.keys();

out << "Keys:" << endl;
for (QString key : keys) {
    out << key << endl;
} 

```

同样，我们打印字典的所有键。 `keys()`方法返回一个列表，其中包含字典中的所有键。

```cpp
QMapIterator<QString, int> it(items);

```

`QMapIterator`是`QMap`的 Java 样式的迭代器。 它可用于遍历映射元素。

```cpp
while (it.hasNext()) {
    it.next();
    out << it.key() << ": " << it.value() << endl;    
}

```

在迭代器的帮助下，我们遍历了映射的所有元素。 `key()`方法返回当前键，`value()`方法返回当前值。

输出：

```cpp
$ ./myqmap 
Values:
3
7
5
Keys:
books
bottles
coins
Pairs:
books: 3
bottles: 7
coins: 5

```

## 自定义类排序

在下面的示例中，我们将在`QList`中对自定义类的对象进行排序。

`book.h`

```cpp
class Book {

    public:
        Book(QString, QString);
        QString getAuthor() const;
        QString getTitle() const;

    private:            
        QString author;
        QString title;    
};

```

这是我们的自定义`Book`类的头文件。

`book.cpp`

```cpp
#include <QString>
#include "book.h"

Book::Book(QString auth, QString tit) {

    author = auth;
    title = tit;
}

QString Book::getAuthor() const {

    return author;
}

QString Book::getTitle() const {

    return title;
}

```

这是`Book`类的实现； 我们有两种访问器方法。

`sortcustomclass.cpp`

```cpp
#include <QTextStream>
#include <QList>
#include <algorithm> 
#include "book.h"

bool compareByTitle(const Book &b1, const Book &b2) {

  return b1.getTitle() < b2.getTitle();
}

int main(void) {

    QTextStream out(stdout);

    QList<Book> books = {
        Book("Jack London", "The Call of the Wild"),
        Book("Honoré de Balzac", "Father Goriot"),
        Book("Leo Tolstoy", "War and Peace"),
        Book("Gustave Flaubert", "Sentimental education"),
        Book("Guy de Maupassant", "Une vie"),
        Book("William Shakespeare", "Hamlet")
    };

    std::sort(books.begin(), books.end(), compareByTitle);

    for (Book book : books) {
        out << book.getAuthor() << ": " << book.getTitle() << endl;
    }
}

```

在示例中，我们创建了一些书本对象，并使用`std::sort`算法对其进行排序。

```cpp
bool compareByTitle(const Book &b1, const Book &b2) {

  return b1.getTitle() < b2.getTitle();
}

```

`compareByTitle()`是排序算法使用的比较功能。

```cpp
std::sort(books.begin(), books.end(), compareByTitle);

```

`std::sort`算法按书名对列表中的书进行排序。

输出：

```cpp
$ ./sortcustomclass 
Honoré de Balzac: Father Goriot
William Shakespeare: Hamlet
Gustave Flaubert: Sentimental education
Jack London: The Call of the Wild
Guy de Maupassant: Une vie
Leo Tolstoy: War and Peace

```

在本章中，我们使用了 Qt 的容器。