Qt中的Java风格迭代器

Java风格迭代器

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

注意:新代码应使用STL风格迭代器,因为这些更高效,并且可以与 Qt 的和 STL 的泛型算法一起使用。

容器只读迭代器读写迭代器
QList<T>, QQueue<T>, QStack<T>,QListIterator<T>QMutableListIterator<T>
QSet<T>QSetIterator<T>QMutableSetIterator<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>

在这次讨论中,我们将集中在 QListQMap。对于 QSet 的迭代器具有与 QList 的迭代器完全相同的接口;同样,对于 QHash 的迭代器也有与 QMap 的迭代器相同的接口。

STL风格迭代器不同,Java风格迭代器是在项目之间而不是直接在项目上指出的。因此,它们可能指向容器非常开始的地方(在第一个项目之前),在容器的非常结束处(在最后一个项目之后),或在两个项目之间。下面的图表显示了包含四个项目的列表示例中的有效迭代器位置(用红色箭头表示)

以下是一个典型循环,按顺序迭代通过 QList<QString> 的所有元素

QList<QString> list = {"A", "B", "C", "D"};

QListIterator<QString> i(list);
while (i.hasNext())
    QString s = i.next();

它的工作方式如下:要迭代的 QList 被传递给 QListIterator 构造器。那时,迭代器位于列表中的第一个项目前面(项目“A”之前)。然后我们调用 hasNext() 来检查迭代器之后是否有项目。如果有,我们调用 next() 来跳过该项目。next() 函数返回它跳过的项目。对于 QList<QString>,该项目是 QString 类型。

以下是如何在 QList 中逆向迭代的示例

QListIterator<QString> i(list);
i.toBack();
while (i.hasPrevious())
    QString s = i.previous();

代码是对称的,正向迭代时的行为如此,除了我们首先调用toBack()()将迭代器移动到列表最后一个元素之后。

下面的图展示了调用next()()和previous()()对迭代器的影响

下表总结了QListIterator API

函数行为
toFront()将迭代器移动到列表的前端(在第一个元素之前)
toBack()将迭代器移动到列表的后端(在最后一个元素之后)
hasNext()如果迭代器不在列表的末尾,则返回true
next()返回下一个元素并将迭代器向前推进一个位置
peekNext()返回下一个元素而不移动迭代器
hasPrevious()如果迭代器不在列表的开头,则返回true
previous()返回前一个元素并将迭代器向后移动一个位置
peekPrevious()返回前一个元素而不移动迭代器

QListIterator在迭代时没有提供插入或删除列表中项的函数。为了实现这一点,您必须使用QMutableListIterator。以下是一个示例,我们在QList<int>中使用QMutableListIterator删除所有奇数。

QMutableListIterator<int> i(list);
while (i.hasNext()) {
    if (i.next() % 2 != 0)
        i.remove();
}

循环中的next()调用每一次都执行。它跳过列表中的下一个元素。调用<嘲笑 href="qmutablelistiterator.html#remove" translate="no">remove()()函数从列表中删除我们跳过的最后一个元素。对remove()的调用不会使迭代器失效,因此可以安全地继续使用它。这也适用于反向迭代。

QMutableListIterator<int> i(list);
i.toBack();
while (i.hasPrevious()) {
    if (i.previous() % 2 != 0)
        i.remove();
}

如果我们只想修改现有项的值,我们可以使用setValue()。在下面的代码中,我们用128替换任何大于128的值。

QMutableListIterator<int> i(list);
while (i.hasNext()) {
    if (i.next() > 128)
        i.setValue(128);
}

和<嘲笑 href="qmutablelistiterator.html#remove" translate="no">remove()一样,<嘲笑 href="qmutablelistiterator.html#setValue" translate="no">setValue()作用于我们跳过的最后一个元素。如果我们正向迭代,这是迭代器之前的那个元素;如果我们反向迭代,这是迭代器之后的那个元素。

<嘲笑 href="qmutablelistiterator.html#next" translate="no">next()()函数返回列表中项的非const引用。对于简单的操作,我们甚至不需要<嘲笑 href="qmutablelistiterator.html#setValue" translate="no">setValue()。

QMutableListIterator<int> i(list);
while (i.hasNext())
    i.next() *= 2;

如上所述,<嘲笑 href="qset.html" translate="no">QSet的迭代器类和<嘲笑 href="qlist.html" translate="no">QList的迭代器类具有完全相同的API。现在我们将转向<嘲笑 href="qmapiterator.html" translate="no">QMapIterator,它有些不同,因为它在键(值)对上迭代。

就像<嘲笑 href="qlistiterator.html" translate="no">QListIterator一样,<嘲笑 href="qmapiterator.html" translate="no">QMapIterator提供了toFront、<嘲笑 href="qmapiterator.html#toBack" translate="no">toBack、<嘲笑 href="qmapiterator.html#hasNext" translate="no">hasNext、<嘲笑 href="qmapiterator.html#next" translate="no">next、<嘲笑 href="qmapiterator.html#peekNext" translate="no">peekNext、<嘲笑 href="qmapiterator.html#hasPrevious" translate="no">hasPrevious、<嘲笑 href="qmapiterator.html#previous" translate="no">previous和peekPrevious。可以通过对next()、peekNext()、previous()或peekPrevious()返回的对象调用key()和value()提取键和值组件。

以下示例删除所有首都名称以"City"结尾的(首都,国家)对

QMap<QString, QString> map = {
    {"Paris", "France"},
    {"Guatemala City", "Guatemala"},
    {"Mexico City", "Mexico"},
    {"Moscow", "Russia"}
};
...

QMutableMapIterator<QString, QString> i(map);
while (i.hasNext()) {
    if (i.next().key().endsWith("City"))
        i.remove();
}

QMapIterator 还提供了一个直接在迭代器上操作并返回迭代器跳过的最后一个项的键和值的 key() 和 value() 函数。例如,以下代码将 QMap 的内容复制到 QHash

QMap<int, QWidget *> map;
QHash<int, QWidget *> hash;

QMapIterator<int, QWidget *> i(map);
while (i.hasNext()) {
    i.next();
    hash.insert(i.key(), i.value());
}

如果我们想遍历具有相同值的所有项,可以使用 findNext() 或 findPrevious()。以下是一个示例,展示了如何删除所有具有特定值的项

QMutableMapIterator<int, QWidget *> i(map);
while (i.findNext(widget))
    i.remove();

© 2024 Qt公司有限公司。本文档中包含的文档贡献主义者的版权。本文档根据由自由软件基金会发布的 GNU自由文档许可证版本1.3 的条款进行许可。Qt及其相关标志是芬兰及其它世界各地的Qt公司注册的商标。所有其他商标均属于其各自拥有者。