1:
37:
38:
39: package ;
40:
41: import ;
42:
43:
48:
49: public class EnumMap<K extends Enum<K>, V>
50: extends AbstractMap<K, V>
51: implements Cloneable, Serializable
52: {
53: private static final long serialVersionUID = 458661240069192865L;
54:
55: V[] store;
56: int cardinality;
57: Class<K> enumClass;
58:
59:
62: transient Set<Map.Entry<K, V>> entries;
63:
64: static final Object emptySlot = new Object();
65:
66: public EnumMap(Class<K> keyType)
67: {
68: store = (V[]) new Object[keyType.getEnumConstants().length];
69: Arrays.fill(store, emptySlot);
70: cardinality = 0;
71: enumClass = keyType;
72: }
73:
74: public EnumMap(EnumMap<K, ? extends V> map)
75: {
76: store = (V[]) map.store.clone();
77: cardinality = map.cardinality;
78: enumClass = map.enumClass;
79: }
80:
81: public EnumMap(Map<K, ? extends V> map)
82: {
83: if (map instanceof EnumMap)
84: {
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;
89: }
90: else
91: {
92: for (K key : map.keySet())
93: {
94: V value = map.get(key);
95: if (store == null)
96: {
97: enumClass = key.getDeclaringClass();
98: store = (V[]) new Object[enumClass.getEnumConstants().length];
99: }
100: int o = key.ordinal();
101: if (store[o] == emptySlot)
102: ++cardinality;
103: store[o] = value;
104: }
105:
106: if (store == null)
107: throw new IllegalArgumentException("no elements in map");
108: }
109: }
110:
111: public int size()
112: {
113: return cardinality;
114: }
115:
116: public boolean containsValue(Object value)
117: {
118: for (V i : store)
119: {
120: if (i != emptySlot && AbstractCollection.equals(i , value))
121: return true;
122: }
123: return false;
124: }
125:
126: public boolean containsKey(Object key)
127: {
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;
134: }
135:
136: public V get(Object key)
137: {
138: if (! (key instanceof Enum))
139: return null;
140: Enum<K> e = (Enum<K>) key;
141: if (e.getDeclaringClass() != enumClass)
142: return null;
143: return store[e.ordinal()];
144: }
145:
146: public V put(K key, V value)
147: {
148: int o = key.ordinal();
149: V result;
150: if (store[o] == emptySlot)
151: {
152: result = null;
153: ++cardinality;
154: }
155: else
156: result = store[o];
157: store[o] = value;
158: return result;
159: }
160:
161: public V remove(Object key)
162: {
163: if (! (key instanceof Enum))
164: return null;
165: Enum<K> e = (Enum<K>) key;
166: if (e.getDeclaringClass() != enumClass)
167: return null;
168: V result = store[e.ordinal()];
169: if (result == emptySlot)
170: result = null;
171: else
172: --cardinality;
173: store[e.ordinal()] = (V) emptySlot;
174: return result;
175: }
176:
177: public void putAll(Map<? extends K, ? extends V> map)
178: {
179: for (K key : map.keySet())
180: {
181: V value = map.get(key);
182:
183: int o = key.ordinal();
184: if (store[o] == emptySlot)
185: ++cardinality;
186: store[o] = value;
187: }
188: }
189:
190: public void clear()
191: {
192: Arrays.fill(store, emptySlot);
193: cardinality = 0;
194: }
195:
196: public Set<K> keySet()
197: {
198: if (keys == null)
199: {
200: keys = new AbstractSet<K>()
201: {
202: public int size()
203: {
204: return cardinality;
205: }
206:
207: public Iterator<K> iterator()
208: {
209: return new Iterator<K>()
210: {
211: int count = 0;
212: int index = -1;
213:
214: public boolean hasNext()
215: {
216: return count < cardinality;
217: }
218:
219: public K next()
220: {
221: ++count;
222: for (++index; store[index] == emptySlot; ++index)
223: ;
224: return enumClass.getEnumConstants()[index];
225: }
226:
227: public void remove()
228: {
229: --cardinality;
230: store[index] = (V) emptySlot;
231: }
232: };
233: }
234:
235: public void clear()
236: {
237: EnumMap.this.clear();
238: }
239:
240: public boolean contains(Object o)
241: {
242: return contains(o);
243: }
244:
245: public boolean remove(Object o)
246: {
247: return EnumMap.this.remove(o) != null;
248: }
249: };
250: }
251: return keys;
252: }
253:
254: public Collection<V> values()
255: {
256: if (values == null)
257: {
258: values = new AbstractCollection<V>()
259: {
260: public int size()
261: {
262: return cardinality;
263: }
264:
265: public Iterator<V> iterator()
266: {
267: return new Iterator<V>()
268: {
269: int count = 0;
270: int index = -1;
271:
272: public boolean hasNext()
273: {
274: return count < cardinality;
275: }
276:
277: public V next()
278: {
279: ++count;
280: for (++index; store[index] == emptySlot; ++index)
281: ;
282: return store[index];
283: }
284:
285: public void remove()
286: {
287: --cardinality;
288: store[index] = (V) emptySlot;
289: }
290: };
291: }
292:
293: public void clear()
294: {
295: EnumMap.this.clear();
296: }
297: };
298: }
299: return values;
300: }
301:
302: public Set<Map.Entry<K, V>> entrySet()
303: {
304: if (entries == null)
305: {
306: entries = new AbstractSet<Map.Entry<K, V>>()
307: {
308: public int size()
309: {
310: return cardinality;
311: }
312:
313: public Iterator<Map.Entry<K, V>> iterator()
314: {
315: return new Iterator<Map.Entry<K, V>>()
316: {
317: int count = 0;
318: int index = -1;
319:
320: public boolean hasNext()
321: {
322: return count < cardinality;
323: }
324:
325: public Map.Entry<K,V> next()
326: {
327: ++count;
328: for (++index; store[index] == emptySlot; ++index)
329: ;
330:
331:
332: return new AbstractMap.SimpleEntry<K, V>(enumClass.getEnumConstants()[index],
333: store[index])
334: {
335: public V setValue(V newVal)
336: {
337: value = newVal;
338: return put(key, newVal);
339: }
340: };
341: }
342:
343: public void remove()
344: {
345: --cardinality;
346: store[index] = (V) emptySlot;
347: }
348: };
349: }
350:
351: public void clear()
352: {
353: EnumMap.this.clear();
354: }
355:
356: public boolean contains(Object o)
357: {
358: if (! (o instanceof Map.Entry))
359: return false;
360: Map.Entry<K, V> other = (Map.Entry<K, V>) o;
361: return (containsKey(other.getKey())
362: && AbstractCollection.equals(get(other.getKey()),
363: other.getValue()));
364: }
365:
366: public boolean remove(Object o)
367: {
368: if (! (o instanceof Map.Entry))
369: return false;
370: Map.Entry<K, V> other = (Map.Entry<K, V>) o;
371: return EnumMap.this.remove(other.getKey()) != null;
372: }
373: };
374: }
375: return entries;
376: }
377:
378: public boolean equals(Object o)
379: {
380: if (! (o instanceof EnumMap))
381: return false;
382: EnumMap<K, V> other = (EnumMap<K, V>) o;
383: if (other.enumClass != enumClass || other.cardinality != cardinality)
384: return false;
385: return Arrays.equals(store, other.store);
386: }
387:
388: public EnumMap<K, V> clone()
389: {
390:
391: return new EnumMap(this);
392: }
393:
394: }