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)
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
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
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. */
41 import java
.io
.Serializable
;
44 * @author Tom Tromey (tromey@redhat.com)
45 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
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;
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
);
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
;
92 for (K key
: map
.keySet())
94 V value
= map
.get(key
);
97 enumClass
= key
.getDeclaringClass();
98 store
= (V
[]) new Object
[enumClass
.getEnumConstants().length
];
100 int o
= key
.ordinal();
101 if (store
[o
] == emptySlot
)
105 // There must be a single element.
107 throw new IllegalArgumentException("no elements in map");
116 public boolean containsValue(Object value
)
120 if (i
!= emptySlot
&& AbstractCollection
.equals(i
, value
))
126 public boolean containsKey(Object key
)
128 if (! (key
instanceof Enum
))
130 Enum
<K
> e
= (Enum
<K
>) key
;
131 if (e
.getDeclaringClass() != enumClass
)
133 return store
[e
.ordinal()] != emptySlot
;
136 public V
get(Object key
)
138 if (! (key
instanceof Enum
))
140 Enum
<K
> e
= (Enum
<K
>) key
;
141 if (e
.getDeclaringClass() != enumClass
)
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();
151 if (store
[o
] == emptySlot
)
162 public V
remove(Object key
)
164 if (! (key
instanceof Enum
))
166 Enum
<K
> e
= (Enum
<K
>) key
;
167 if (e
.getDeclaringClass() != enumClass
)
169 V result
= store
[e
.ordinal()];
170 if (result
== emptySlot
)
174 store
[e
.ordinal()] = (V
) emptySlot
;
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
)
193 Arrays
.fill(store
, emptySlot
);
197 public Set
<K
> keySet()
201 keys
= new AbstractSet
<K
>()
208 public Iterator
<K
> iterator()
210 return new Iterator
<K
>()
215 public boolean hasNext()
217 return count
< cardinality
;
223 for (++index
; store
[index
] == emptySlot
; ++index
)
225 return enumClass
.getEnumConstants()[index
];
231 store
[index
] = (V
) emptySlot
;
238 EnumMap
.this.clear();
241 public boolean contains(Object o
)
246 public boolean remove(Object o
)
248 return EnumMap
.this.remove(o
) != null;
255 public Collection
<V
> values()
259 values
= new AbstractCollection
<V
>()
266 public Iterator
<V
> iterator()
268 return new Iterator
<V
>()
273 public boolean hasNext()
275 return count
< cardinality
;
281 for (++index
; store
[index
] == emptySlot
; ++index
)
289 store
[index
] = (V
) emptySlot
;
296 EnumMap
.this.clear();
303 public Set
<Map
.Entry
<K
, V
>> entrySet()
307 entries
= new AbstractSet
<Map
.Entry
<K
, V
>>()
314 public Iterator
<Map
.Entry
<K
, V
>> iterator()
316 return new Iterator
<Map
.Entry
<K
, V
>>()
321 public boolean hasNext()
323 return count
< cardinality
;
326 public Map
.Entry
<K
,V
> next()
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
],
336 public V
setValue(V newVal
)
339 return put(key
, newVal
);
347 store
[index
] = (V
) emptySlot
;
354 EnumMap
.this.clear();
357 public boolean contains(Object o
)
359 if (! (o
instanceof Map
.Entry
))
361 Map
.Entry
<K
, V
> other
= (Map
.Entry
<K
, V
>) o
;
362 return (containsKey(other
.getKey())
363 && AbstractCollection
.equals(get(other
.getKey()),
367 public boolean remove(Object o
)
369 if (! (o
instanceof Map
.Entry
))
371 Map
.Entry
<K
, V
> other
= (Map
.Entry
<K
, V
>) o
;
372 return EnumMap
.this.remove(other
.getKey()) != null;
379 public boolean equals(Object o
)
381 if (! (o
instanceof EnumMap
))
383 EnumMap
<K
, V
> other
= (EnumMap
<K
, V
>) o
;
384 if (other
.enumClass
!= enumClass
|| other
.cardinality
!= cardinality
)
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
)
401 result
.store
= (V
[]) store
.clone();