summaryrefslogtreecommitdiffstats
path: root/src/corelib/doc/src/java-style-iterators.qdoc
blob: 7e3c9db69b7e9155f6276efa12fd27c9d7dbdab3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \page java-style-iterators.html
    \title Java-style Iterators in Qt
    \ingroup groups
    \ingroup qt-basic-concepts
    \brief Java style iterators for Qt's containers.

    \tableofcontents

    \section1 Java-Style Iterators

    For each container class, there are two Java-style iterator data
    types: one that provides read-only access and one that provides
    read-write access.

    \note New code should use \l{STL-Style iterators} since these are more efficient
    and can be used together with Qt's and STL's \l{generic algorithms}.

    \table
    \header \li Containers                        \li Read-only iterator
                                                  \li Read-write iterator
    \row    \li QList<T>, QQueue<T>, QStack<T>,   \li QListIterator<T>
                                                  \li QMutableListIterator<T>
    \row    \li QSet<T>                           \li QSetIterator<T>
                                                  \li QMutableSetIterator<T>
    \row    \li QMap<Key, T>, QMultiMap<Key, T>   \li QMapIterator<Key, T>
                                                  \li QMutableMapIterator<Key, T>
    \row    \li QHash<Key, T>, QMultiHash<Key, T> \li QHashIterator<Key, T>
                                                  \li QMutableHashIterator<Key, T>
    \endtable

    In this discussion, we will concentrate on QList and QMap. The
    iterator types for QSet have exactly
    the same interface as QList's iterators; similarly, the iterator
    types for QHash have the same interface as QMap's iterators.

    Unlike \l{STL-Style iterators}, Java-style iterators point \e between items
    rather than directly \e at items. For this reason, they are either pointing
    to the very beginning of the container (before the first item), at the very
    end of the container (after the last item), or between two items. The
    diagram below shows the valid iterator positions as red arrows for a list
    containing four items:

    \image javaiterators1.png

    Here's a typical loop for iterating through all the elements of a
    QList<QString> in order:

    \snippet code/doc_src_containers.cpp 1

    It works as follows: The QList to iterate over is passed to the
    QListIterator constructor. At that point, the iterator is located
    just in front of the first item in the list (before item "A").
    Then we call \l{QListIterator::hasNext()}{hasNext()} to
    check whether there is an item after the iterator. If there is, we
    call \l{QListIterator::next()}{next()} to jump over that
    item. The next() function returns the item that it jumps over. For
    a QList<QString>, that item is of type QString.

    Here's how to iterate backward in a QList:

    \snippet code/doc_src_containers.cpp 2

    The code is symmetric with iterating forward, except that we
    start by calling \l{QListIterator::toBack()}{toBack()}
    to move the iterator after the last item in the list.

    The diagram below illustrates the effect of calling
    \l{QListIterator::next()}{next()} and
    \l{QListIterator::previous()}{previous()} on an iterator:

    \image javaiterators2.png

    The following table summarizes the QListIterator API:

    \table
    \header \li Function \li Behavior
    \row    \li \l{QListIterator::toFront()}{toFront()}
            \li Moves the iterator to the front of the list (before the first item)
    \row    \li \l{QListIterator::toBack()}{toBack()}
            \li Moves the iterator to the back of the list (after the last item)
    \row    \li \l{QListIterator::hasNext()}{hasNext()}
            \li Returns \c true if the iterator isn't at the back of the list
    \row    \li \l{QListIterator::next()}{next()}
            \li Returns the next item and advances the iterator by one position
    \row    \li \l{QListIterator::peekNext()}{peekNext()}
            \li Returns the next item without moving the iterator
    \row    \li \l{QListIterator::hasPrevious()}{hasPrevious()}
            \li Returns \c true if the iterator isn't at the front of the list
    \row    \li \l{QListIterator::previous()}{previous()}
            \li Returns the previous item and moves the iterator back by one position
    \row    \li \l{QListIterator::peekPrevious()}{peekPrevious()}
            \li Returns the previous item without moving the iterator
    \endtable

    QListIterator provides no functions to insert or remove items
    from the list as we iterate. To accomplish this, you must use
    QMutableListIterator. Here's an example where we remove all
    odd numbers from a QList<int> using QMutableListIterator:

    \snippet code/doc_src_containers.cpp 3

    The next() call in the loop is made every time. It jumps over the
    next item in the list. The
    \l{QMutableListIterator::remove()}{remove()} function removes the
    last item that we jumped over from the list. The call to
    \l{QMutableListIterator::remove()}{remove()} does not invalidate
    the iterator, so it is safe to continue using it. This works just
    as well when iterating backward:

    \snippet code/doc_src_containers.cpp 4

    If we just want to modify the value of an existing item, we can
    use \l{QMutableListIterator::setValue()}{setValue()}. In the code
    below, we replace any value larger than 128 with 128:

    \snippet code/doc_src_containers.cpp 5

    Just like \l{QMutableListIterator::remove()}{remove()},
    \l{QMutableListIterator::setValue()}{setValue()} operates on the
    last item that we jumped over. If we iterate forward, this is the
    item just before the iterator; if we iterate backward, this is
    the item just after the iterator.

    The \l{QMutableListIterator::next()}{next()} function returns a
    non-const reference to the item in the list. For simple
    operations, we don't even need
    \l{QMutableListIterator::setValue()}{setValue()}:

    \snippet code/doc_src_containers.cpp 6

    As mentioned above QSet's iterator
    classes have exactly the same API as QList's. We will now turn to
    QMapIterator, which is somewhat different because it iterates on
    (key, value) pairs.

    Like QListIterator, QMapIterator provides
    \l{QMapIterator::toFront()}{toFront()},
    \l{QMapIterator::toBack()}{toBack()},
    \l{QMapIterator::hasNext()}{hasNext()},
    \l{QMapIterator::next()}{next()},
    \l{QMapIterator::peekNext()}{peekNext()},
    \l{QMapIterator::hasPrevious()}{hasPrevious()},
    \l{QMapIterator::previous()}{previous()}, and
    \l{QMapIterator::peekPrevious()}{peekPrevious()}. The key and
    value components are extracted by calling \l{QMapIterator::key()}{key()} and \l{QMapIterator::value()}{value()} on
    the object returned by next(), peekNext(), previous(), or
    peekPrevious().

    The following example removes all (capital, country) pairs where
    the capital's name ends with "City":

    \snippet code/doc_src_containers.cpp 7

    QMapIterator also provides a \l{QMapIterator::key()}{key()} and a \l{QMapIterator::value()}{value()} function that
    operate directly on the iterator and that return the key and
    value of the last item that the iterator jumped above. For
    example, the following code copies the contents of a QMap into a
    QHash:

    \snippet code/doc_src_containers.cpp 8

    If we want to iterate through all the items with the same
    value, we can use \l{QMapIterator::findNext()}{findNext()}
    or \l{QMapIterator::findPrevious()}{findPrevious()}.
    Here's an example where we remove all the items with a particular
    value:

    \snippet code/doc_src_containers.cpp 9

*/