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: V o = store[e.ordinal()];
144: return o == emptySlot ? null : o;
145: }
146:
147: public V put(K key, V value)
148: {
149: int o = key.ordinal();
150: V result;
151: if (store[o] == emptySlot)
152: {
153: result = null;
154: ++cardinality;
155: }
156: else
157: result = store[o];
158: store[o] = value;
159: return result;
160: }
161:
162: public V remove(Object key)
163: {
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;
176: }
177:
178: public void putAll(Map<? extends K, ? extends V> map)
179: {
180: for (K key : map.keySet())
181: {
182: V value = map.get(key);
183:
184: int o = key.ordinal();
185: if (store[o] == emptySlot)
186: ++cardinality;
187: store[o] = value;
188: }
189: }
190:
191: public void clear()
192: {
193: Arrays.fill(store, emptySlot);
194: cardinality = 0;
195: }
196:
197: public Set<K> keySet()
198: {
199: if (keys == null)
200: {
201: keys = new AbstractSet<K>()
202: {
203: public int size()
204: {
205: return cardinality;
206: }
207:
208: public Iterator<K> iterator()
209: {
210: return new Iterator<K>()
211: {
212: int count = 0;
213: int index = -1;
214:
215: public boolean hasNext()
216: {
217: return count < cardinality;
218: }
219:
220: public K next()
221: {
222: ++count;
223: for (++index; store[index] == emptySlot; ++index)
224: ;
225: return enumClass.getEnumConstants()[index];
226: }
227:
228: public void remove()
229: {
230: --cardinality;
231: store[index] = (V) emptySlot;
232: }
233: };
234: }
235:
236: public void clear()
237: {
238: EnumMap.this.clear();
239: }
240:
241: public boolean contains(Object o)
242: {
243: return contains(o);
244: }
245:
246: public boolean remove(Object o)
247: {
248: return EnumMap.this.remove(o) != null;
249: }
250: };
251: }
252: return keys;
253: }
254:
255: public Collection<V> values()
256: {
257: if (values == null)
258: {
259: values = new AbstractCollection<V>()
260: {
261: public int size()
262: {
263: return cardinality;
264: }
265:
266: public Iterator<V> iterator()
267: {
268: return new Iterator<V>()
269: {
270: int count = 0;
271: int index = -1;
272:
273: public boolean hasNext()
274: {
275: return count < cardinality;
276: }
277:
278: public V next()
279: {
280: ++count;
281: for (++index; store[index] == emptySlot; ++index)
282: ;
283: return store[index];
284: }
285:
286: public void remove()
287: {
288: --cardinality;
289: store[index] = (V) emptySlot;
290: }
291: };
292: }
293:
294: public void clear()
295: {
296: EnumMap.this.clear();
297: }
298: };
299: }
300: return values;
301: }
302:
303: public Set<Map.Entry<K, V>> entrySet()
304: {
305: if (entries == null)
306: {
307: entries = new AbstractSet<Map.Entry<K, V>>()
308: {
309: public int size()
310: {
311: return cardinality;
312: }
313:
314: public Iterator<Map.Entry<K, V>> iterator()
315: {
316: return new Iterator<Map.Entry<K, V>>()
317: {
318: int count = 0;
319: int index = -1;
320:
321: public boolean hasNext()
322: {
323: return count < cardinality;
324: }
325:
326: public Map.Entry<K,V> next()
327: {
328: ++count;
329: for (++index; store[index] == emptySlot; ++index)
330: ;
331:
332:
333: return new AbstractMap.SimpleEntry<K, V>(enumClass.getEnumConstants()[index],
334: store[index])
335: {
336: public V setValue(V newVal)
337: {
338: value = newVal;
339: return put(key, newVal);
340: }
341: };
342: }
343:
344: public void remove()
345: {
346: --cardinality;
347: store[index] = (V) emptySlot;
348: }
349: };
350: }
351:
352: public void clear()
353: {
354: EnumMap.this.clear();
355: }
356:
357: public boolean contains(Object o)
358: {
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()));
365: }
366:
367: public boolean remove(Object o)
368: {
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;
373: }
374: };
375: }
376: return entries;
377: }
378:
379: public boolean equals(Object o)
380: {
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);
387: }
388:
389: public EnumMap<K, V> clone()
390: {
391: EnumMap<K, V> result;
392: try
393: {
394: result = (EnumMap<K, V>) super.clone();
395: }
396: catch (CloneNotSupportedException ignore)
397: {
398:
399: result = null;
400: }
401: result.store = (V[]) store.clone();
402: return result;
403: }
404:
405: }