Merged with mainline at revision 128810.
[official-gcc.git] / libjava / classpath / java / util / EnumMap.java
blobb7187b935f23126d87b1f856dc9445fc0fbe2575
1 /* EnumMap.java - Map where keys are enum constants
2 Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.util;
41 import java.io.Serializable;
43 /**
44 * @author Tom Tromey (tromey@redhat.com)
45 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
46 * @since 1.5
49 public class EnumMap<K extends Enum<K>, V>
50 extends AbstractMap<K, V>
51 implements Cloneable, Serializable
53 private static final long serialVersionUID = 458661240069192865L;
55 V[] store;
56 int cardinality;
57 Class<K> enumClass;
59 /**
60 * The cache for {@link #entrySet()}.
62 transient Set<Map.Entry<K, V>> entries;
64 static final Object emptySlot = new Object();
66 public EnumMap(Class<K> keyType)
68 store = (V[]) new Object[keyType.getEnumConstants().length];
69 Arrays.fill(store, emptySlot);
70 cardinality = 0;
71 enumClass = keyType;
74 public EnumMap(EnumMap<K, ? extends V> map)
76 store = (V[]) map.store.clone();
77 cardinality = map.cardinality;
78 enumClass = map.enumClass;
81 public EnumMap(Map<K, ? extends V> map)
83 if (map instanceof EnumMap)
85 EnumMap<K, ? extends V> other = (EnumMap<K, ? extends V>) map;
86 store = (V[]) other.store.clone();
87 cardinality = other.cardinality;
88 enumClass = other.enumClass;
90 else
92 for (K key : map.keySet())
94 V value = map.get(key);
95 if (store == null)
97 enumClass = key.getDeclaringClass();
98 store = (V[]) new Object[enumClass.getEnumConstants().length];
100 int o = key.ordinal();
101 if (store[o] == emptySlot)
102 ++cardinality;
103 store[o] = value;
105 // There must be a single element.
106 if (store == null)
107 throw new IllegalArgumentException("no elements in map");
111 public int size()
113 return cardinality;
116 public boolean containsValue(Object value)
118 for (V i : store)
120 if (i != emptySlot && AbstractCollection.equals(i , value))
121 return true;
123 return false;
126 public boolean containsKey(Object key)
128 if (! (key instanceof Enum))
129 return false;
130 Enum<K> e = (Enum<K>) key;
131 if (e.getDeclaringClass() != enumClass)
132 return false;
133 return store[e.ordinal()] != emptySlot;
136 public V get(Object key)
138 if (! (key instanceof Enum))
139 return null;
140 Enum<K> e = (Enum<K>) key;
141 if (e.getDeclaringClass() != enumClass)
142 return null;
143 V o = store[e.ordinal()];
144 return o == emptySlot ? null : o;
147 public V put(K key, V value)
149 int o = key.ordinal();
150 V result;
151 if (store[o] == emptySlot)
153 result = null;
154 ++cardinality;
156 else
157 result = store[o];
158 store[o] = value;
159 return result;
162 public V remove(Object key)
164 if (! (key instanceof Enum))
165 return null;
166 Enum<K> e = (Enum<K>) key;
167 if (e.getDeclaringClass() != enumClass)
168 return null;
169 V result = store[e.ordinal()];
170 if (result == emptySlot)
171 result = null;
172 else
173 --cardinality;
174 store[e.ordinal()] = (V) emptySlot;
175 return result;
178 public void putAll(Map<? extends K, ? extends V> map)
180 for (K key : map.keySet())
182 V value = map.get(key);
184 int o = key.ordinal();
185 if (store[o] == emptySlot)
186 ++cardinality;
187 store[o] = value;
191 public void clear()
193 Arrays.fill(store, emptySlot);
194 cardinality = 0;
197 public Set<K> keySet()
199 if (keys == null)
201 keys = new AbstractSet<K>()
203 public int size()
205 return cardinality;
208 public Iterator<K> iterator()
210 return new Iterator<K>()
212 int count = 0;
213 int index = -1;
215 public boolean hasNext()
217 return count < cardinality;
220 public K next()
222 ++count;
223 for (++index; store[index] == emptySlot; ++index)
225 return enumClass.getEnumConstants()[index];
228 public void remove()
230 --cardinality;
231 store[index] = (V) emptySlot;
236 public void clear()
238 EnumMap.this.clear();
241 public boolean contains(Object o)
243 return contains(o);
246 public boolean remove(Object o)
248 return EnumMap.this.remove(o) != null;
252 return keys;
255 public Collection<V> values()
257 if (values == null)
259 values = new AbstractCollection<V>()
261 public int size()
263 return cardinality;
266 public Iterator<V> iterator()
268 return new Iterator<V>()
270 int count = 0;
271 int index = -1;
273 public boolean hasNext()
275 return count < cardinality;
278 public V next()
280 ++count;
281 for (++index; store[index] == emptySlot; ++index)
283 return store[index];
286 public void remove()
288 --cardinality;
289 store[index] = (V) emptySlot;
294 public void clear()
296 EnumMap.this.clear();
300 return values;
303 public Set<Map.Entry<K, V>> entrySet()
305 if (entries == null)
307 entries = new AbstractSet<Map.Entry<K, V>>()
309 public int size()
311 return cardinality;
314 public Iterator<Map.Entry<K, V>> iterator()
316 return new Iterator<Map.Entry<K, V>>()
318 int count = 0;
319 int index = -1;
321 public boolean hasNext()
323 return count < cardinality;
326 public Map.Entry<K,V> next()
328 ++count;
329 for (++index; store[index] == emptySlot; ++index)
331 // FIXME: we could just return something that
332 // only knows the index. That would be cleaner.
333 return new AbstractMap.SimpleEntry<K, V>(enumClass.getEnumConstants()[index],
334 store[index])
336 public V setValue(V newVal)
338 value = newVal;
339 return put(key, newVal);
344 public void remove()
346 --cardinality;
347 store[index] = (V) emptySlot;
352 public void clear()
354 EnumMap.this.clear();
357 public boolean contains(Object o)
359 if (! (o instanceof Map.Entry))
360 return false;
361 Map.Entry<K, V> other = (Map.Entry<K, V>) o;
362 return (containsKey(other.getKey())
363 && AbstractCollection.equals(get(other.getKey()),
364 other.getValue()));
367 public boolean remove(Object o)
369 if (! (o instanceof Map.Entry))
370 return false;
371 Map.Entry<K, V> other = (Map.Entry<K, V>) o;
372 return EnumMap.this.remove(other.getKey()) != null;
376 return entries;
379 public boolean equals(Object o)
381 if (! (o instanceof EnumMap))
382 return false;
383 EnumMap<K, V> other = (EnumMap<K, V>) o;
384 if (other.enumClass != enumClass || other.cardinality != cardinality)
385 return false;
386 return Arrays.equals(store, other.store);
389 public EnumMap<K, V> clone()
391 EnumMap<K, V> result;
394 result = (EnumMap<K, V>) super.clone();
396 catch (CloneNotSupportedException ignore)
398 // Can't happen.
399 result = null;
401 result.store = (V[]) store.clone();
402 return result;