1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.collections.iterators;
18
19 import java.util.Iterator;
20 import java.util.Map;
21
22 import org.apache.commons.collections.MapIterator;
23 import org.apache.commons.collections.ResettableIterator;
24
25 /**
26 * Implements a <code>MapIterator</code> using a Map entrySet.
27 * Reverse iteration is not supported.
28 * <pre>
29 * MapIterator it = map.mapIterator();
30 * while (it.hasNext()) {
31 * Object key = it.next();
32 * Object value = it.getValue();
33 * it.setValue(newValue);
34 * }
35 * </pre>
36 *
37 * @since 3.0
38 * @version $Id: EntrySetMapIterator.java 1429905 2013-01-07 17:15:14Z ggregory $
39 */
40 public class EntrySetMapIterator<K, V> implements MapIterator<K, V>, ResettableIterator<K> {
41
42 private final Map<K, V> map;
43 private Iterator<Map.Entry<K, V>> iterator;
44 private Map.Entry<K, V> last;
45 private boolean canRemove = false;
46
47 /**
48 * Constructor.
49 *
50 * @param map the map to iterate over
51 */
52 public EntrySetMapIterator(final Map<K, V> map) {
53 super();
54 this.map = map;
55 this.iterator = map.entrySet().iterator();
56 }
57
58 //-----------------------------------------------------------------------
59 /**
60 * Checks to see if there are more entries still to be iterated.
61 *
62 * @return <code>true</code> if the iterator has more elements
63 */
64 public boolean hasNext() {
65 return iterator.hasNext();
66 }
67
68 /**
69 * Gets the next <em>key</em> from the <code>Map</code>.
70 *
71 * @return the next key in the iteration
72 * @throws java.util.NoSuchElementException if the iteration is finished
73 */
74 public K next() {
75 last = iterator.next();
76 canRemove = true;
77 return last.getKey();
78 }
79
80 //-----------------------------------------------------------------------
81 /**
82 * Removes the last returned key from the underlying <code>Map</code>.
83 * <p>
84 * This method can be called once per call to <code>next()</code>.
85 *
86 * @throws UnsupportedOperationException if remove is not supported by the map
87 * @throws IllegalStateException if <code>next()</code> has not yet been called
88 * @throws IllegalStateException if <code>remove()</code> has already been called
89 * since the last call to <code>next()</code>
90 */
91 public void remove() {
92 if (canRemove == false) {
93 throw new IllegalStateException("Iterator remove() can only be called once after next()");
94 }
95 iterator.remove();
96 last = null;
97 canRemove = false;
98 }
99
100 //-----------------------------------------------------------------------
101 /**
102 * Gets the current key, which is the key returned by the last call
103 * to <code>next()</code>.
104 *
105 * @return the current key
106 * @throws IllegalStateException if <code>next()</code> has not yet been called
107 */
108 public K getKey() {
109 if (last == null) {
110 throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
111 }
112 return last.getKey();
113 }
114
115 /**
116 * Gets the current value, which is the value associated with the last key
117 * returned by <code>next()</code>.
118 *
119 * @return the current value
120 * @throws IllegalStateException if <code>next()</code> has not yet been called
121 */
122 public V getValue() {
123 if (last == null) {
124 throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
125 }
126 return last.getValue();
127 }
128
129 /**
130 * Sets the value associated with the current key.
131 *
132 * @param value the new value
133 * @return the previous value
134 * @throws UnsupportedOperationException if setValue is not supported by the map
135 * @throws IllegalStateException if <code>next()</code> has not yet been called
136 * @throws IllegalStateException if <code>remove()</code> has been called since the
137 * last call to <code>next()</code>
138 */
139 public V setValue(final V value) {
140 if (last == null) {
141 throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
142 }
143 return last.setValue(value);
144 }
145
146 //-----------------------------------------------------------------------
147 /**
148 * Resets the state of the iterator.
149 */
150 public void reset() {
151 iterator = map.entrySet().iterator();
152 last = null;
153 canRemove = false;
154 }
155
156 /**
157 * Gets the iterator as a String.
158 *
159 * @return a string version of the iterator
160 */
161 @Override
162 public String toString() {
163 if (last != null) {
164 return "MapIterator[" + getKey() + "=" + getValue() + "]";
165 }
166 return "MapIterator[]";
167 }
168
169 }