Iteratoren im Java-Stil in Qt

Iteratoren im Java-Stil

Für jede Containerklasse gibt es zwei Iterator-Datentypen im Java-Stil: einen, der nur Lesezugriff bietet, und einen, der Lese- und Schreibzugriff bietet.

Hinweis: Neuer Code sollte Iteratoren im STL-Stil verwenden, da diese effizienter sind und zusammen mit den generic algorithms von Qt und STL verwendet werden können.

BehältnisseNur-Lese-IteratorLese-Schreib-Iterator
QList<T>, QQueue<T>, QStack<T>,QListIterator<T>QMutableListIterator<T>
QSet<T>QSetIterator<T>QMutableSetIterator<T>
QMap<Schlüssel, T>, QMultiMap<Schlüssel, T>QMapIterator<Schlüssel, T>QMutableMapIterator<Schlüssel, T>
QHash<Schlüssel, T>, QMultiHash<Schlüssel, T>QHashIterator<Schlüssel, T>QMutableHashIterator<Schlüssel, T>

In dieser Diskussion werden wir uns auf QList und QMap konzentrieren. Die Iteratortypen für QSet haben genau die gleiche Schnittstelle wie die Iteratoren von QList; ebenso haben die Iteratortypen für QHash die gleiche Schnittstelle wie die Iteratoren von QMap.

Im Gegensatz zu Iteratoren im STL-Stil zeigen Iteratoren im Java-Stil zwischen Elementen und nicht direkt auf Elemente. Aus diesem Grund zeigen sie entweder auf den Anfang des Containers (vor dem ersten Element), auf das Ende des Containers (nach dem letzten Element) oder zwischen zwei Elementen. Das folgende Diagramm zeigt die gültigen Iteratorpositionen als rote Pfeile für eine Liste mit vier Elementen:

Hier ist eine typische Schleife, um alle Elemente eines QList<QString> der Reihe nach durchzugehen:

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

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

Sie funktioniert wie folgt: Die QList, über die iteriert werden soll, wird an den QListIterator Konstruktor übergeben. Zu diesem Zeitpunkt befindet sich der Iterator direkt vor dem ersten Element der Liste (vor dem Element "A"). Dann rufen wir hasNext() auf, um zu prüfen, ob nach dem Iterator ein Element vorhanden ist. Wenn ja, rufen wir next() auf, um dieses Element zu überspringen. Die Funktion next() gibt das Element zurück, das übersprungen wird. Bei einem QList<QString> ist dieses Element vom Typ QString.

Hier sehen Sie, wie Sie in einer QList rückwärts iterieren:

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

Der Code ist symmetrisch zum Vorwärts-Iterieren, mit dem Unterschied, dass wir mit dem Aufruf von toBack() beginnen, um den Iterator nach dem letzten Element in der Liste zu verschieben.

Das folgende Diagramm veranschaulicht die Auswirkungen der Aufrufe next() und previous() auf einen Iterator:

In der folgenden Tabelle ist die API von QListIterator zusammengefasst:

FunktionVerhalten
toFront()Verschiebt den Iterator an den Anfang der Liste (vor das erste Element)
toBack()Bewegt den Iterator an das Ende der Liste (nach dem letzten Eintrag)
hasNext()Gibt true zurück, wenn der Iterator nicht am Ende der Liste steht
next()Gibt das nächste Element zurück und rückt den Iterator um eine Position vor
peekNext()Gibt das nächste Element zurück, ohne den Iterator zu verschieben
hasPrevious()Gibt true zurück, wenn der Iterator nicht am Anfang der Liste steht
previous()Gibt das vorherige Element zurück und verschiebt den Iterator um eine Position zurück
peekPrevious()Gibt das vorherige Element zurück, ohne den Iterator zu verschieben

QListIterator bietet keine Funktionen zum Einfügen oder Entfernen von Elementen aus der Liste, während wir iterieren. Um dies zu erreichen, müssen Sie QMutableListIterator verwenden. Hier ein Beispiel, in dem alle ungeraden Zahlen aus einer QList<int> mit QMutableListIterator entfernt werden:

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

Der next()-Aufruf in der Schleife wird jedes Mal ausgeführt. Er springt über das nächste Element in der Liste. Die Funktion remove() entfernt das letzte Element, das wir übersprungen haben, aus der Liste. Der Aufruf von remove() macht den Iterator nicht ungültig, so dass man ihn weiter verwenden kann. Dies funktioniert auch beim Rückwärts-Iterieren:

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

Wenn wir nur den Wert eines vorhandenen Elements ändern wollen, können wir setValue() verwenden. Im folgenden Code wird jeder Wert, der größer als 128 ist, durch 128 ersetzt:

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

Genau wie remove() wirkt setValue() auf das letzte Element, das wir übersprungen haben. Wenn wir vorwärts iterieren, ist dies das Element unmittelbar vor dem Iterator; wenn wir rückwärts iterieren, ist dies das Element unmittelbar nach dem Iterator.

Die Funktion next() gibt einen nicht-konstanten Verweis auf das Element in der Liste zurück. Für einfache Operationen brauchen wir nicht einmal setValue():

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

Wie bereits erwähnt, haben die Iterator-Klassen von QSet genau die gleiche API wie die von QList. Wir werden uns nun QMapIterator zuwenden, das etwas anders ist, weil es auf (Schlüssel, Wert)-Paaren iteriert.

Wie QListIterator bietet QMapIterator toFront (), toBack(), hasNext(), next(), peekNext(), hasPrevious(), previous() und peekPrevious(). Die Schlüssel- und Wertkomponenten werden durch den Aufruf von key() und value() für das von next(), peekNext(), previous() oder peekPrevious() zurückgegebene Objekt extrahiert.

Das folgende Beispiel entfernt alle (Hauptstadt, Land) Paare, bei denen der Name der Hauptstadt mit "Stadt" endet:

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 bietet auch eine key() und eine value() Funktion, die direkt auf den Iterator wirken und den Schlüssel und den Wert des letzten Elements zurückgeben, über das der Iterator gesprungen ist. Der folgende Code kopiert zum Beispiel den Inhalt von QMap in 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());
}

Wenn wir alle Elemente mit demselben Wert durchlaufen wollen, können wir findNext() oder findPrevious() verwenden. Hier ein Beispiel, bei dem alle Einträge mit einem bestimmten Wert entfernt werden:

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.