Qt 中 Java 风格的迭代器
Java 风格迭代器
每个容器类都有两种 Java 风格的迭代器数据类型:一种提供只读访问,另一种提供读写访问。
注: 新代码应使用STL 样式的迭代器,因为这些迭代器效率更高,可与 Qt XML 和 STL 的generic algorithms 一起使用。
容器 | 只读迭代器 | 读写迭代器 |
---|---|---|
QList<t>,QQueue<t>,QStack<t>、 | QListIterator<T> | QMutableListIterator<T> |
QSet<T> | QSetIterator<T> | QMutableSetIterator<T> |
QMap<键,T>,QMultiMap<键,T | QMapIterator<键,T | QMutableMapIterator<键,T |
QHash<键,T>,QMultiHash<键,T | QHashIterator<键,T | QMutableHashIterator<键,T |
在本讨论中,我们将集中讨论QList 和QMap 。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 在迭代过程中,我们没有提供从列表中插入或移除项的函数。要做到这一点,必须使用 。下面是一个示例,我们使用 删除 <int> 中的所有奇数:QMutableListIterator QMutableListIterator QList
QMutableListIterator<int> i(list); while (i.hasNext()) { if (i.next() % 2 != 0) i.remove(); }
循环中的 next() 调用每次都会执行。它跳转到列表中的下一个项目。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); }
与remove() 一样,setValue() 对我们跳转的最后一个项目进行操作。如果向前迭代,则是迭代器之前的项目;如果向后迭代,则是迭代器之后的项目。
next() 函数返回一个指向列表中项目的非常数引用。对于简单的操作,我们甚至不需要setValue():
QMutableListIterator<int> i(list); while (i.hasNext()) i.next() *= 2;
如上所述,QSet 的迭代器类与QList 的 API 完全相同。现在我们来看看QMapIterator ,它的不同之处在于它可以迭代(键、值)对。
与QListIterator 一样,QMapIterator 提供了toFront(),toBack(),hasNext(),next(),peekNext(),hasPrevious(),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();
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.