001package com.hfg.util.collection; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.HashMap; 006import java.util.Map; 007import java.util.Set; 008import java.util.function.BiConsumer; 009import java.util.function.BiFunction; 010import java.util.function.Function; 011 012//------------------------------------------------------------------------------ 013/** 014 * HashMap that preserves the key order. 015 * @author J. Alex Taylor, hairyfatguy.com 016 */ 017//------------------------------------------------------------------------------ 018// com.hfg Library 019// 020// This library is free software; you can redistribute it and/or 021// modify it under the terms of the GNU Lesser General Public 022// License as published by the Free Software Foundation; either 023// version 2.1 of the License, or (at your option) any later version. 024// 025// This library is distributed in the hope that it will be useful, 026// but WITHOUT ANY WARRANTY; without even the implied warranty of 027// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 028// Lesser General Public License for more details. 029// 030// You should have received a copy of the GNU Lesser General Public 031// License along with this library; if not, write to the Free Software 032// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 033// 034// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 035// jataylor@hairyfatguy.com 036//------------------------------------------------------------------------------ 037 038public class OrderedMap<K, V> extends HashMap<K, V> 039{ 040 private OrderedSet<K> mOrderedKeys; 041 042 //########################################################################## 043 // CONSTRUCTORS 044 //########################################################################## 045 046 //-------------------------------------------------------------------------- 047 public OrderedMap() 048 { 049 super(); 050 mOrderedKeys = new OrderedSet<>(); 051 } 052 053 //-------------------------------------------------------------------------- 054 public OrderedMap(int inInitialCapacity) 055 { 056 super(inInitialCapacity); 057 mOrderedKeys = new OrderedSet<>(inInitialCapacity); 058 } 059 060 //-------------------------------------------------------------------------- 061 public OrderedMap(int inInitialCapacity, float loadFactor) 062 { 063 super(inInitialCapacity, loadFactor); 064 mOrderedKeys = new OrderedSet<>(inInitialCapacity); 065 } 066 067 //-------------------------------------------------------------------------- 068 public OrderedMap(Map<? extends K,? extends V> m) 069 { 070 super(m); 071 mOrderedKeys = new OrderedSet<>(m.keySet()); 072 } 073 074 //########################################################################## 075 // PUBLIC METHODS 076 //########################################################################## 077 078 //-------------------------------------------------------------------------- 079 @Override 080 public void clear() 081 { 082 mOrderedKeys.clear(); 083 super.clear(); 084 } 085 086 //-------------------------------------------------------------------------- 087 @Override 088 public V put(K inKey, V inValue) 089 { 090 mOrderedKeys.add(inKey); 091 return super.put(inKey, inValue); 092 } 093 094 //-------------------------------------------------------------------------- 095 @Override 096 public void putAll(Map<? extends K,? extends V> m) 097 { 098 for (K key : m.keySet()) 099 { 100 put(key, m.get(key)); 101 } 102 } 103 104 //-------------------------------------------------------------------------- 105 @Override 106 public V putIfAbsent(K inKey, V inValue) 107 { 108 mOrderedKeys.add(inKey); 109 return super.putIfAbsent(inKey, inValue); 110 } 111 112 //-------------------------------------------------------------------------- 113 @Override 114 public V computeIfPresent(K inKey, 115 BiFunction<? super K, ? super V, ? extends V> inRemappingFunction) 116 { 117 mOrderedKeys.add(inKey); 118 return super.computeIfPresent(inKey, inRemappingFunction); 119 } 120 121 //-------------------------------------------------------------------------- 122 @Override 123 public V computeIfAbsent(K inKey, 124 Function<? super K, ? extends V> inRemappingFunction) 125 { 126 mOrderedKeys.add(inKey); 127 return super.computeIfAbsent(inKey, inRemappingFunction); 128 } 129 130 //-------------------------------------------------------------------------- 131 @Override 132 public V compute(K inKey, 133 BiFunction<? super K, ? super V, ? extends V> inRemappingFunction) 134 { 135 mOrderedKeys.add(inKey); 136 return super.compute(inKey, inRemappingFunction); 137 } 138 139 //-------------------------------------------------------------------------- 140 @Override 141 public V merge(K inKey, V inValue, 142 BiFunction<? super V, ? super V, ? extends V> inRemappingFunction) 143 { 144 mOrderedKeys.add(inKey); 145 return super.merge(inKey, inValue, inRemappingFunction); 146 } 147 148 //-------------------------------------------------------------------------- 149 @Override 150 public Collection<V> values() 151 { 152 Collection<V> values = null; 153 if (CollectionUtil.hasValues(this)) 154 { 155 values = new ArrayList<V>(size()); 156 for (K key : keySet()) 157 { 158 values.add(get(key)); 159 } 160 } 161 162 return values; 163 } 164 165 //-------------------------------------------------------------------------- 166 @Override 167 public V remove(Object inKey) 168 { 169 mOrderedKeys.remove(inKey); 170 return super.remove(inKey); 171 } 172 173 //-------------------------------------------------------------------------- 174 @Override 175 public OrderedSet<K> keySet() 176 { 177 return mOrderedKeys; 178 } 179 180 //-------------------------------------------------------------------------- 181 @Override 182 public Set<Entry<K, V>> entrySet() 183 { 184 Set<Entry<K, V>> orderedEntries = new OrderedSet<>(size()); 185 186 for (K key : keySet()) 187 { 188 orderedEntries.add(new OrderedEntry(key, get(key))); 189 } 190 191 return orderedEntries; 192 } 193 194 //-------------------------------------------------------------------------- 195 @Override 196 public void forEach(BiConsumer<? super K, ? super V> inAction) 197 { 198 for (K key : keySet()) 199 { 200 inAction.accept(key, get(key)); 201 } 202 } 203 204 205 private class OrderedEntry implements Map.Entry<K, V> 206 { 207 private K mKey; 208 private V mValue; 209 210 //----------------------------------------------------------------------- 211 public OrderedEntry(K inKey, V inValue) 212 { 213 mKey = inKey; 214 mValue = inValue; 215 } 216 217 //----------------------------------------------------------------------- 218 @Override 219 public K getKey() 220 { 221 return mKey; 222 } 223 224 //----------------------------------------------------------------------- 225 @Override 226 public V getValue() 227 { 228 return mValue; 229 } 230 231 //----------------------------------------------------------------------- 232 @Override 233 public V setValue(V inValue) 234 { 235 V oldValue = mValue; 236 mValue = inValue; 237 238 return oldValue; 239 } 240 } 241}