001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.iterators; 018 019import java.util.Iterator; 020import java.util.Map; 021 022import org.apache.commons.collections4.MapIterator; 023import org.apache.commons.collections4.ResettableIterator; 024 025/** 026 * Implements a <code>MapIterator</code> using a Map entrySet. 027 * Reverse iteration is not supported. 028 * <pre> 029 * MapIterator it = map.mapIterator(); 030 * while (it.hasNext()) { 031 * Object key = it.next(); 032 * Object value = it.getValue(); 033 * it.setValue(newValue); 034 * } 035 * </pre> 036 * 037 * @since 3.0 038 * @version $Id: EntrySetMapIterator.html 972421 2015-11-14 20:00:04Z tn $ 039 */ 040public class EntrySetMapIterator<K, V> implements MapIterator<K, V>, ResettableIterator<K> { 041 042 private final Map<K, V> map; 043 private Iterator<Map.Entry<K, V>> iterator; 044 private Map.Entry<K, V> last; 045 private boolean canRemove = false; 046 047 /** 048 * Constructor. 049 * 050 * @param map the map to iterate over 051 */ 052 public EntrySetMapIterator(final Map<K, V> map) { 053 super(); 054 this.map = map; 055 this.iterator = map.entrySet().iterator(); 056 } 057 058 //----------------------------------------------------------------------- 059 /** 060 * Checks to see if there are more entries still to be iterated. 061 * 062 * @return <code>true</code> if the iterator has more elements 063 */ 064 public boolean hasNext() { 065 return iterator.hasNext(); 066 } 067 068 /** 069 * Gets the next <em>key</em> from the <code>Map</code>. 070 * 071 * @return the next key in the iteration 072 * @throws java.util.NoSuchElementException if the iteration is finished 073 */ 074 public K next() { 075 last = iterator.next(); 076 canRemove = true; 077 return last.getKey(); 078 } 079 080 //----------------------------------------------------------------------- 081 /** 082 * Removes the last returned key from the underlying <code>Map</code>. 083 * <p> 084 * This method can be called once per call to <code>next()</code>. 085 * 086 * @throws UnsupportedOperationException if remove is not supported by the map 087 * @throws IllegalStateException if <code>next()</code> has not yet been called 088 * @throws IllegalStateException if <code>remove()</code> has already been called 089 * since the last call to <code>next()</code> 090 */ 091 public void remove() { 092 if (canRemove == false) { 093 throw new IllegalStateException("Iterator remove() can only be called once after next()"); 094 } 095 iterator.remove(); 096 last = null; 097 canRemove = false; 098 } 099 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}