Home | History | Annotate | Download | only in util
      1 /* Licensed to the Apache Software Foundation (ASF) under one or more
      2  * contributor license agreements.  See the NOTICE file distributed with
      3  * this work for additional information regarding copyright ownership.
      4  * The ASF licenses this file to You under the Apache License, Version 2.0
      5  * (the "License"); you may not use this file except in compliance with
      6  * the License.  You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package java.util;
     18 
     19 import java.io.IOException;
     20 import java.io.ObjectInputStream;
     21 import java.io.ObjectOutputStream;
     22 import java.io.Serializable;
     23 import java.lang.reflect.Array;
     24 
     25 /**
     26  * An {@code Map} specialized for use with {@code Enum} types as keys.
     27  */
     28 public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements
     29         Serializable, Cloneable, Map<K, V> {
     30 
     31     // BEGIN android-changed
     32     // added implements Map<K, V> for apicheck
     33     // END android-changed
     34 
     35     private static final long serialVersionUID = 458661240069192865L;
     36 
     37     private Class<K> keyType;
     38 
     39     transient Enum[] keys;
     40 
     41     transient Object[] values;
     42 
     43     transient boolean[] hasMapping;
     44 
     45     private transient int mappingsCount;
     46 
     47     transient int enumSize;
     48 
     49     private transient EnumMapEntrySet<K, V> entrySet = null;
     50 
     51     private static class Entry<KT extends Enum<KT>, VT> extends
     52             MapEntry<KT, VT> {
     53         private final EnumMap<KT, VT> enumMap;
     54 
     55         private final int ordinal;
     56 
     57         Entry(KT theKey, VT theValue, EnumMap<KT, VT> em) {
     58             super(theKey, theValue);
     59             enumMap = em;
     60             ordinal = ((Enum) theKey).ordinal();
     61         }
     62 
     63         @SuppressWarnings("unchecked")
     64         @Override
     65         public boolean equals(Object object) {
     66             if (!enumMap.hasMapping[ordinal]) {
     67                 return false;
     68             }
     69             boolean isEqual = false;
     70             if (object instanceof Map.Entry) {
     71                 Map.Entry<KT, VT> entry = (Map.Entry<KT, VT>) object;
     72                 Object enumKey = entry.getKey();
     73                 if (key.equals(enumKey)) {
     74                     Object theValue = entry.getValue();
     75                     if (enumMap.values[ordinal] == null) {
     76                         isEqual = (theValue == null);
     77                     } else {
     78                         isEqual = enumMap.values[ordinal].equals(theValue);
     79                     }
     80                 }
     81             }
     82             return isEqual;
     83         }
     84 
     85         @Override
     86         public int hashCode() {
     87             return (enumMap.keys[ordinal] == null ? 0 : enumMap.keys[ordinal]
     88                     .hashCode())
     89                     ^ (enumMap.values[ordinal] == null ? 0
     90                             : enumMap.values[ordinal].hashCode());
     91         }
     92 
     93         @SuppressWarnings("unchecked")
     94         @Override
     95         public KT getKey() {
     96             checkEntryStatus();
     97             return (KT) enumMap.keys[ordinal];
     98         }
     99 
    100         @SuppressWarnings("unchecked")
    101         @Override
    102         public VT getValue() {
    103             checkEntryStatus();
    104             return (VT) enumMap.values[ordinal];
    105         }
    106 
    107         @SuppressWarnings("unchecked")
    108         @Override
    109         public VT setValue(VT value) {
    110             checkEntryStatus();
    111             return enumMap.put((KT) enumMap.keys[ordinal], value);
    112         }
    113 
    114         @Override
    115         public String toString() {
    116             StringBuilder result = new StringBuilder(enumMap.keys[ordinal]
    117                     .toString());
    118             result.append("=");
    119             result.append(enumMap.values[ordinal] == null
    120                     ? "null" : enumMap.values[ordinal].toString());
    121             return result.toString();
    122         }
    123 
    124         private void checkEntryStatus() {
    125             if (!enumMap.hasMapping[ordinal]) {
    126                 throw new IllegalStateException();
    127             }
    128         }
    129     }
    130 
    131     private static class EnumMapIterator<E, KT extends Enum<KT>, VT> implements
    132             Iterator<E> {
    133         int position = 0;
    134 
    135         int prePosition = -1;
    136 
    137         final EnumMap<KT, VT> enumMap;
    138 
    139         final MapEntry.Type<E, KT, VT> type;
    140 
    141         EnumMapIterator(MapEntry.Type<E, KT, VT> value, EnumMap<KT, VT> em) {
    142             enumMap = em;
    143             type = value;
    144         }
    145 
    146         public boolean hasNext() {
    147             int length = enumMap.enumSize;
    148             for (; position < length; position++) {
    149                 if (enumMap.hasMapping[position]) {
    150                     break;
    151                 }
    152             }
    153             return position != length;
    154         }
    155 
    156         @SuppressWarnings("unchecked")
    157         public E next() {
    158             if (!hasNext()) {
    159                 throw new NoSuchElementException();
    160             }
    161             prePosition = position++;
    162             return type.get(new MapEntry(enumMap.keys[prePosition],
    163                     enumMap.values[prePosition]));
    164         }
    165 
    166         public void remove() {
    167             checkStatus();
    168             if (enumMap.hasMapping[prePosition]) {
    169                 enumMap.remove(enumMap.keys[prePosition]);
    170             }
    171             prePosition = -1;
    172         }
    173 
    174         @Override
    175         @SuppressWarnings("unchecked")
    176         public String toString() {
    177             if (prePosition == -1) {
    178                 return super.toString();
    179             }
    180             return type.get(
    181                     new MapEntry(enumMap.keys[prePosition],
    182                             enumMap.values[prePosition])).toString();
    183         }
    184 
    185         private void checkStatus() {
    186             if (prePosition == -1) {
    187                 throw new IllegalStateException();
    188             }
    189         }
    190     }
    191 
    192     private static class EnumMapKeySet<KT extends Enum<KT>, VT> extends
    193             AbstractSet<KT> {
    194         private final EnumMap<KT, VT> enumMap;
    195 
    196         EnumMapKeySet(EnumMap<KT, VT> em) {
    197             enumMap = em;
    198         }
    199 
    200         @Override
    201         public void clear() {
    202             enumMap.clear();
    203         }
    204 
    205         @Override
    206         public boolean contains(Object object) {
    207             return enumMap.containsKey(object);
    208         }
    209 
    210         @Override
    211         @SuppressWarnings("unchecked")
    212         public Iterator iterator() {
    213             return new EnumMapIterator<KT, KT, VT>(
    214                     new MapEntry.Type<KT, KT, VT>() {
    215                         public KT get(MapEntry<KT, VT> entry) {
    216                             return entry.key;
    217                         }
    218                     }, enumMap);
    219         }
    220 
    221         @Override
    222         @SuppressWarnings("unchecked")
    223         public boolean remove(Object object) {
    224             if (contains(object)) {
    225                 enumMap.remove(object);
    226                 return true;
    227             }
    228             return false;
    229         }
    230 
    231         @Override
    232         public int size() {
    233             return enumMap.size();
    234         }
    235     }
    236 
    237     private static class EnumMapValueCollection<KT extends Enum<KT>, VT>
    238             extends AbstractCollection<VT> {
    239         private final EnumMap<KT, VT> enumMap;
    240 
    241         EnumMapValueCollection(EnumMap<KT, VT> em) {
    242             enumMap = em;
    243         }
    244 
    245         @Override
    246         public void clear() {
    247             enumMap.clear();
    248         }
    249 
    250         @Override
    251         public boolean contains(Object object) {
    252             return enumMap.containsValue(object);
    253         }
    254 
    255         @SuppressWarnings("unchecked")
    256         @Override
    257         public Iterator iterator() {
    258             return new EnumMapIterator<VT, KT, VT>(
    259                     new MapEntry.Type<VT, KT, VT>() {
    260                         public VT get(MapEntry<KT, VT> entry) {
    261                             return entry.value;
    262                         }
    263                     }, enumMap);
    264         }
    265 
    266         @Override
    267         public boolean remove(Object object) {
    268             if (object == null) {
    269                 for (int i = 0; i < enumMap.enumSize; i++) {
    270                     if (enumMap.hasMapping[i] && enumMap.values[i] == null) {
    271                         enumMap.remove(enumMap.keys[i]);
    272                         return true;
    273                     }
    274                 }
    275             } else {
    276                 for (int i = 0; i < enumMap.enumSize; i++) {
    277                     if (enumMap.hasMapping[i]
    278                             && object.equals(enumMap.values[i])) {
    279                         enumMap.remove(enumMap.keys[i]);
    280                         return true;
    281                     }
    282                 }
    283             }
    284             return false;
    285         }
    286 
    287         @Override
    288         public int size() {
    289             return enumMap.size();
    290         }
    291     }
    292 
    293     private static class EnumMapEntryIterator<E, KT extends Enum<KT>, VT>
    294             extends EnumMapIterator<E, KT, VT> {
    295         EnumMapEntryIterator(MapEntry.Type<E, KT, VT> value, EnumMap<KT, VT> em) {
    296             super(value, em);
    297         }
    298 
    299         @SuppressWarnings("unchecked")
    300         @Override
    301         public E next() {
    302             if (!hasNext()) {
    303                 throw new NoSuchElementException();
    304             }
    305             prePosition = position++;
    306             return type.get(new Entry<KT, VT>((KT) enumMap.keys[prePosition],
    307                     (VT) enumMap.values[prePosition], enumMap));
    308         }
    309     }
    310 
    311     private static class EnumMapEntrySet<KT extends Enum<KT>, VT> extends
    312             AbstractSet<Map.Entry<KT, VT>> {
    313         private final EnumMap<KT, VT> enumMap;
    314 
    315         EnumMapEntrySet(EnumMap<KT, VT> em) {
    316             enumMap = em;
    317         }
    318 
    319         @Override
    320         public void clear() {
    321             enumMap.clear();
    322         }
    323 
    324         @Override
    325         public boolean contains(Object object) {
    326             boolean isEqual = false;
    327             if (object instanceof Map.Entry) {
    328                 Object enumKey = ((Map.Entry) object).getKey();
    329                 Object enumValue = ((Map.Entry) object).getValue();
    330                 if (enumMap.containsKey(enumKey)) {
    331                     VT value = enumMap.get(enumKey);
    332                     if (value == null) {
    333                         isEqual = enumValue == null;
    334                     } else {
    335                         isEqual = value.equals(enumValue);
    336                     }
    337                 }
    338             }
    339             return isEqual;
    340         }
    341 
    342         @Override
    343         public Iterator<Map.Entry<KT, VT>> iterator() {
    344             return new EnumMapEntryIterator<Map.Entry<KT, VT>, KT, VT>(
    345                     new MapEntry.Type<Map.Entry<KT, VT>, KT, VT>() {
    346                         public Map.Entry<KT, VT> get(MapEntry<KT, VT> entry) {
    347                             return entry;
    348                         }
    349                     }, enumMap);
    350         }
    351 
    352         @Override
    353         public boolean remove(Object object) {
    354             if (contains(object)) {
    355                 enumMap.remove(((Map.Entry) object).getKey());
    356                 return true;
    357             }
    358             return false;
    359         }
    360 
    361         @Override
    362         public int size() {
    363             return enumMap.size();
    364         }
    365 
    366         @Override
    367         public Object[] toArray() {
    368             Object[] entryArray = new Object[enumMap.size()];
    369             return toArray(entryArray);
    370         }
    371 
    372         @SuppressWarnings("unchecked")
    373         @Override
    374         public Object[] toArray(Object[] array) {
    375             int size = enumMap.size();
    376             int index = 0;
    377             Object[] entryArray = array;
    378             if (size > array.length) {
    379                 Class<?> clazz = array.getClass().getComponentType();
    380                 entryArray = (Object[]) Array.newInstance(clazz, size);
    381             }
    382             Iterator<Map.Entry<KT, VT>> iter = iterator();
    383             for (; index < size; index++) {
    384                 Map.Entry<KT, VT> entry = iter.next();
    385                 entryArray[index] = new MapEntry<KT, VT>(entry.getKey(), entry
    386                         .getValue());
    387             }
    388             if (index < array.length) {
    389                 entryArray[index] = null;
    390             }
    391             return entryArray;
    392         }
    393     }
    394 
    395     /**
    396      * Constructs an empty {@code EnumMap} using the given key type.
    397      *
    398      * @param keyType
    399      *            the class object giving the type of the keys used by this {@code EnumMap}.
    400      * @throws NullPointerException
    401      *             if {@code keyType} is {@code null}.
    402      */
    403     public EnumMap(Class<K> keyType) {
    404         initialization(keyType);
    405     }
    406 
    407     /**
    408      * Constructs an {@code EnumMap} using the same key type as the given {@code EnumMap} and
    409      * initially containing the same mappings.
    410      *
    411      * @param map
    412      *            the {@code EnumMap} from which this {@code EnumMap} is initialized.
    413      * @throws NullPointerException
    414      *             if {@code map} is {@code null}.
    415      */
    416     public EnumMap(EnumMap<K, ? extends V> map) {
    417         initialization(map);
    418     }
    419 
    420     /**
    421      * Constructs an {@code EnumMap} initialized from the given map. If the given map
    422      * is an {@code EnumMap} instance, this constructor behaves in the exactly the same
    423      * way as {@link EnumMap#EnumMap(EnumMap)}}. Otherwise, the given map
    424      * should contain at least one mapping.
    425      *
    426      * @param map
    427      *            the map from which this {@code EnumMap} is initialized.
    428      * @throws IllegalArgumentException
    429      *             if {@code map} is not an {@code EnumMap} instance and does not contain
    430      *             any mappings.
    431      * @throws NullPointerException
    432      *             if {@code map} is {@code null}.
    433      */
    434     @SuppressWarnings("unchecked")
    435     public EnumMap(Map<K, ? extends V> map) {
    436         if (map instanceof EnumMap) {
    437             initialization((EnumMap<K, V>) map);
    438         } else {
    439             if (map.isEmpty()) {
    440                 throw new IllegalArgumentException("map is empty");
    441             }
    442             Iterator<K> iter = map.keySet().iterator();
    443             K enumKey = iter.next();
    444             Class clazz = enumKey.getClass();
    445             if (clazz.isEnum()) {
    446                 initialization(clazz);
    447             } else {
    448                 initialization(clazz.getSuperclass());
    449             }
    450             putAllImpl(map);
    451         }
    452     }
    453 
    454     /**
    455      * Removes all elements from this {@code EnumMap}, leaving it empty.
    456      *
    457      * @see #isEmpty()
    458      * @see #size()
    459      */
    460     @Override
    461     public void clear() {
    462         Arrays.fill(values, null);
    463         Arrays.fill(hasMapping, false);
    464         mappingsCount = 0;
    465     }
    466 
    467     /**
    468      * Returns a shallow copy of this {@code EnumMap}.
    469      *
    470      * @return a shallow copy of this {@code EnumMap}.
    471      */
    472     @SuppressWarnings("unchecked")
    473     @Override
    474     public EnumMap<K, V> clone() {
    475         try {
    476             EnumMap<K, V> enumMap = (EnumMap<K, V>) super.clone();
    477             enumMap.initialization(this);
    478             return enumMap;
    479         } catch (CloneNotSupportedException e) {
    480             throw new AssertionError(e);
    481         }
    482     }
    483 
    484     /**
    485      * Returns whether this {@code EnumMap} contains the specified key.
    486      *
    487      * @param key
    488      *            the key to search for.
    489      * @return {@code true} if this {@code EnumMap} contains the specified key,
    490      *         {@code false} otherwise.
    491      */
    492     @Override
    493     public boolean containsKey(Object key) {
    494         if (isValidKeyType(key)) {
    495             int keyOrdinal = ((Enum) key).ordinal();
    496             return hasMapping[keyOrdinal];
    497         }
    498         return false;
    499     }
    500 
    501     /**
    502      * Returns whether this {@code EnumMap} contains the specified value.
    503      *
    504      * @param value
    505      *            the value to search for.
    506      * @return {@code true} if this {@code EnumMap} contains the specified value,
    507      *         {@code false} otherwise.
    508      */
    509     @Override
    510     public boolean containsValue(Object value) {
    511         if (value == null) {
    512             for (int i = 0; i < enumSize; i++) {
    513                 if (hasMapping[i] && values[i] == null) {
    514                     return true;
    515                 }
    516             }
    517         } else {
    518             for (int i = 0; i < enumSize; i++) {
    519                 if (hasMapping[i] && value.equals(values[i])) {
    520                     return true;
    521                 }
    522             }
    523         }
    524         return false;
    525     }
    526 
    527     /**
    528      * Returns a {@code Set} containing all of the mappings in this {@code EnumMap}. Each mapping is
    529      * an instance of {@link Map.Entry}. As the {@code Set} is backed by this {@code EnumMap},
    530      * changes in one will be reflected in the other.
    531      * <p>
    532      * The order of the entries in the set will be the order that the enum keys
    533      * were declared in.
    534      *
    535      * @return a {@code Set} of the mappings.
    536      */
    537     @Override
    538     public Set<Map.Entry<K, V>> entrySet() {
    539         if (entrySet == null) {
    540             entrySet = new EnumMapEntrySet<K, V>(this);
    541         }
    542         return entrySet;
    543     }
    544 
    545     /**
    546      * Compares the argument to the receiver, and returns {@code true} if the
    547      * specified {@code Object} is an {@code EnumMap} and both {@code EnumMap}s contain the same mappings.
    548      *
    549      * @param object
    550      *            the {@code Object} to compare with this {@code EnumMap}.
    551      * @return boolean {@code true} if {@code object} is the same as this {@code EnumMap},
    552      *         {@code false} otherwise.
    553      * @see #hashCode()
    554      * @see #entrySet()
    555      */
    556     @SuppressWarnings("unchecked")
    557     @Override
    558     public boolean equals(Object object) {
    559         if (this == object) {
    560             return true;
    561         }
    562         if (!(object instanceof EnumMap)) {
    563             return super.equals(object);
    564         }
    565         EnumMap<K, V> enumMap = (EnumMap<K, V>) object;
    566         if (keyType != enumMap.keyType || size() != enumMap.size()) {
    567             return false;
    568         }
    569         return Arrays.equals(hasMapping, enumMap.hasMapping)
    570                 && Arrays.equals(values, enumMap.values);
    571     }
    572 
    573     /**
    574      * Returns the value of the mapping with the specified key.
    575      *
    576      * @param key
    577      *            the key.
    578      * @return the value of the mapping with the specified key, or {@code null}
    579      *         if no mapping for the specified key is found.
    580      */
    581     @Override
    582     @SuppressWarnings("unchecked")
    583     public V get(Object key) {
    584         if (!isValidKeyType(key)) {
    585             return null;
    586         }
    587         int keyOrdinal = ((Enum) key).ordinal();
    588         return (V) values[keyOrdinal];
    589     }
    590 
    591     /**
    592      * Returns a set of the keys contained in this {@code EnumMap}. The {@code Set} is backed by
    593      * this {@code EnumMap} so changes to one are reflected in the other. The {@code Set} does not
    594      * support adding.
    595      * <p>
    596      * The order of the set will be the order that the enum keys were declared
    597      * in.
    598      *
    599      * @return a {@code Set} of the keys.
    600      */
    601     @Override
    602     public Set<K> keySet() {
    603         if (keySet == null) {
    604             keySet = new EnumMapKeySet<K, V>(this);
    605         }
    606         return keySet;
    607     }
    608 
    609     /**
    610      * Maps the specified key to the specified value.
    611      *
    612      * @param key
    613      *            the key.
    614      * @param value
    615      *            the value.
    616      * @return the value of any previous mapping with the specified key or
    617      *         {@code null} if there was no mapping.
    618      * @throws UnsupportedOperationException
    619      *                if adding to this map is not supported.
    620      * @throws ClassCastException
    621      *                if the class of the key or value is inappropriate for this
    622      *                map.
    623      * @throws IllegalArgumentException
    624      *                if the key or value cannot be added to this map.
    625      * @throws NullPointerException
    626      *                if the key or value is {@code null} and this {@code EnumMap} does not
    627      *                support {@code null} keys or values.
    628      */
    629     @Override
    630     @SuppressWarnings("unchecked")
    631     public V put(K key, V value) {
    632         return putImpl(key, value);
    633     }
    634 
    635     /**
    636      * Copies every mapping in the specified {@code Map} to this {@code EnumMap}.
    637      *
    638      * @param map
    639      *            the {@code Map} to copy mappings from.
    640      * @throws UnsupportedOperationException
    641      *                if adding to this {@code EnumMap} is not supported.
    642      * @throws ClassCastException
    643      *                if the class of a key or value is inappropriate for this
    644      *                {@code EnumMap}.
    645      * @throws IllegalArgumentException
    646      *                if a key or value cannot be added to this map.
    647      * @throws NullPointerException
    648      *                if a key or value is {@code null} and this {@code EnumMap} does not
    649      *                support {@code null} keys or values.
    650      */
    651     @Override
    652     @SuppressWarnings("unchecked")
    653     public void putAll(Map<? extends K, ? extends V> map) {
    654         putAllImpl(map);
    655     }
    656 
    657     /**
    658      * Removes a mapping with the specified key from this {@code EnumMap}.
    659      *
    660      * @param key
    661      *            the key of the mapping to remove.
    662      * @return the value of the removed mapping or {@code null} if no mapping
    663      *         for the specified key was found.
    664      * @throws UnsupportedOperationException
    665      *                if removing from this {@code EnumMap} is not supported.
    666      */
    667     @Override
    668     @SuppressWarnings("unchecked")
    669     public V remove(Object key) {
    670         if (!isValidKeyType(key)) {
    671             return null;
    672         }
    673         int keyOrdinal = ((Enum) key).ordinal();
    674         if (hasMapping[keyOrdinal]) {
    675             hasMapping[keyOrdinal] = false;
    676             mappingsCount--;
    677         }
    678         V oldValue = (V) values[keyOrdinal];
    679         values[keyOrdinal] = null;
    680         return oldValue;
    681     }
    682 
    683     /**
    684      * Returns the number of elements in this {@code EnumMap}.
    685      *
    686      * @return the number of elements in this {@code EnumMap}.
    687      */
    688     @Override
    689     public int size() {
    690         return mappingsCount;
    691     }
    692 
    693     /**
    694      * Returns a {@code Collection} of the values contained in this {@code EnumMap}. The returned
    695      * {@code Collection} complies with the general rule specified in
    696      * {@link Map#values()}. The {@code Collection}'s {@code Iterator} will return the values
    697      * in the their corresponding keys' natural order (the {@code Enum} constants are
    698      * declared in this order).
    699      * <p>
    700      * The order of the values in the collection will be the order that their
    701      * corresponding enum keys were declared in.
    702      *
    703      * @return a collection of the values contained in this {@code EnumMap}.
    704      */
    705     @Override
    706     public Collection<V> values() {
    707         if (valuesCollection == null) {
    708             valuesCollection = new EnumMapValueCollection<K, V>(this);
    709         }
    710         return valuesCollection;
    711     }
    712 
    713     @SuppressWarnings("unchecked")
    714     private void readObject(ObjectInputStream stream) throws IOException,
    715             ClassNotFoundException {
    716         stream.defaultReadObject();
    717         initialization(keyType);
    718         int elementCount = stream.readInt();
    719         Enum<K> enumKey;
    720         Object value;
    721         for (int i = elementCount; i > 0; i--) {
    722             enumKey = (Enum<K>) stream.readObject();
    723             value = stream.readObject();
    724             putImpl((K) enumKey, (V) value);
    725         }
    726     }
    727 
    728     private void writeObject(ObjectOutputStream stream) throws IOException {
    729         stream.defaultWriteObject();
    730         stream.writeInt(mappingsCount);
    731         Iterator<Map.Entry<K, V>> iterator = entrySet().iterator();
    732         while (iterator.hasNext()) {
    733             Map.Entry<K, V> entry = iterator.next();
    734             stream.writeObject(entry.getKey());
    735             stream.writeObject(entry.getValue());
    736         }
    737     }
    738 
    739     private boolean isValidKeyType(Object key) {
    740         if (key != null && keyType.isInstance(key)) {
    741             return true;
    742         }
    743         return false;
    744     }
    745 
    746     @SuppressWarnings("unchecked")
    747     private void initialization(EnumMap enumMap) {
    748         keyType = enumMap.keyType;
    749         keys = enumMap.keys;
    750         enumSize = enumMap.enumSize;
    751         values = enumMap.values.clone();
    752         hasMapping = enumMap.hasMapping.clone();
    753         mappingsCount = enumMap.mappingsCount;
    754     }
    755 
    756     private void initialization(Class<K> type) {
    757         keyType = type;
    758         keys = Enum.getSharedConstants(keyType);
    759         enumSize = keys.length;
    760         values = new Object[enumSize];
    761         hasMapping = new boolean[enumSize];
    762     }
    763 
    764     @SuppressWarnings("unchecked")
    765     private void putAllImpl(Map map) {
    766         Iterator iter = map.entrySet().iterator();
    767         while (iter.hasNext()) {
    768             Map.Entry entry = (Map.Entry) iter.next();
    769             putImpl((K) entry.getKey(), (V) entry.getValue());
    770         }
    771     }
    772 
    773     @SuppressWarnings("unchecked")
    774     private V putImpl(K key, V value) {
    775         if (key == null) {
    776             throw new NullPointerException("key == null");
    777         }
    778         keyType.cast(key); // Called to throw ClassCastException.
    779         int keyOrdinal = key.ordinal();
    780         if (!hasMapping[keyOrdinal]) {
    781             hasMapping[keyOrdinal] = true;
    782             mappingsCount++;
    783         }
    784         V oldValue = (V) values[keyOrdinal];
    785         values[keyOrdinal] = value;
    786         return oldValue;
    787     }
    788 
    789 }
    790