Save This Page
Home » openjdk-7 » java » util » [javadoc | source]
    1   /*
    2    * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.util;
   27   
   28   import java.util.Map.Entry;
   29   import sun.misc.SharedSecrets;
   30   
   31   /**
   32    * A specialized {@link Map} implementation for use with enum type keys.  All
   33    * of the keys in an enum map must come from a single enum type that is
   34    * specified, explicitly or implicitly, when the map is created.  Enum maps
   35    * are represented internally as arrays.  This representation is extremely
   36    * compact and efficient.
   37    *
   38    * <p>Enum maps are maintained in the <i>natural order</i> of their keys
   39    * (the order in which the enum constants are declared).  This is reflected
   40    * in the iterators returned by the collections views ({@link #keySet()},
   41    * {@link #entrySet()}, and {@link #values()}).
   42    *
   43    * <p>Iterators returned by the collection views are <i>weakly consistent</i>:
   44    * they will never throw {@link ConcurrentModificationException} and they may
   45    * or may not show the effects of any modifications to the map that occur while
   46    * the iteration is in progress.
   47    *
   48    * <p>Null keys are not permitted.  Attempts to insert a null key will
   49    * throw {@link NullPointerException}.  Attempts to test for the
   50    * presence of a null key or to remove one will, however, function properly.
   51    * Null values are permitted.
   52   
   53    * <P>Like most collection implementations <tt>EnumMap</tt> is not
   54    * synchronized. If multiple threads access an enum map concurrently, and at
   55    * least one of the threads modifies the map, it should be synchronized
   56    * externally.  This is typically accomplished by synchronizing on some
   57    * object that naturally encapsulates the enum map.  If no such object exists,
   58    * the map should be "wrapped" using the {@link Collections#synchronizedMap}
   59    * method.  This is best done at creation time, to prevent accidental
   60    * unsynchronized access:
   61    *
   62    * <pre>
   63    *     Map&lt;EnumKey, V&gt; m
   64    *         = Collections.synchronizedMap(new EnumMap&lt;EnumKey, V&gt;(...));
   65    * </pre>
   66    *
   67    * <p>Implementation note: All basic operations execute in constant time.
   68    * They are likely (though not guaranteed) to be faster than their
   69    * {@link HashMap} counterparts.
   70    *
   71    * <p>This class is a member of the
   72    * <a href="{@docRoot}/../technotes/guides/collections/index.html">
   73    * Java Collections Framework</a>.
   74    *
   75    * @author Josh Bloch
   76    * @see EnumSet
   77    * @since 1.5
   78    */
   79   public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
   80       implements java.io.Serializable, Cloneable
   81   {
   82       /**
   83        * The <tt>Class</tt> object for the enum type of all the keys of this map.
   84        *
   85        * @serial
   86        */
   87       private final Class<K> keyType;
   88   
   89       /**
   90        * All of the values comprising K.  (Cached for performance.)
   91        */
   92       private transient K[] keyUniverse;
   93   
   94       /**
   95        * Array representation of this map.  The ith element is the value
   96        * to which universe[i] is currently mapped, or null if it isn't
   97        * mapped to anything, or NULL if it's mapped to null.
   98        */
   99       private transient Object[] vals;
  100   
  101       /**
  102        * The number of mappings in this map.
  103        */
  104       private transient int size = 0;
  105   
  106       /**
  107        * Distinguished non-null value for representing null values.
  108        */
  109       private static final Object NULL = new Object();
  110   
  111       private Object maskNull(Object value) {
  112           return (value == null ? NULL : value);
  113       }
  114   
  115       private V unmaskNull(Object value) {
  116           return (V) (value == NULL ? null : value);
  117       }
  118   
  119       private static Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
  120   
  121       /**
  122        * Creates an empty enum map with the specified key type.
  123        *
  124        * @param keyType the class object of the key type for this enum map
  125        * @throws NullPointerException if <tt>keyType</tt> is null
  126        */
  127       public EnumMap(Class<K> keyType) {
  128           this.keyType = keyType;
  129           keyUniverse = getKeyUniverse(keyType);
  130           vals = new Object[keyUniverse.length];
  131       }
  132   
  133       /**
  134        * Creates an enum map with the same key type as the specified enum
  135        * map, initially containing the same mappings (if any).
  136        *
  137        * @param m the enum map from which to initialize this enum map
  138        * @throws NullPointerException if <tt>m</tt> is null
  139        */
  140       public EnumMap(EnumMap<K, ? extends V> m) {
  141           keyType = m.keyType;
  142           keyUniverse = m.keyUniverse;
  143           vals = m.vals.clone();
  144           size = m.size;
  145       }
  146   
  147       /**
  148        * Creates an enum map initialized from the specified map.  If the
  149        * specified map is an <tt>EnumMap</tt> instance, this constructor behaves
  150        * identically to {@link #EnumMap(EnumMap)}.  Otherwise, the specified map
  151        * must contain at least one mapping (in order to determine the new
  152        * enum map's key type).
  153        *
  154        * @param m the map from which to initialize this enum map
  155        * @throws IllegalArgumentException if <tt>m</tt> is not an
  156        *     <tt>EnumMap</tt> instance and contains no mappings
  157        * @throws NullPointerException if <tt>m</tt> is null
  158        */
  159       public EnumMap(Map<K, ? extends V> m) {
  160           if (m instanceof EnumMap) {
  161               EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m;
  162               keyType = em.keyType;
  163               keyUniverse = em.keyUniverse;
  164               vals = em.vals.clone();
  165               size = em.size;
  166           } else {
  167               if (m.isEmpty())
  168                   throw new IllegalArgumentException("Specified map is empty");
  169               keyType = m.keySet().iterator().next().getDeclaringClass();
  170               keyUniverse = getKeyUniverse(keyType);
  171               vals = new Object[keyUniverse.length];
  172               putAll(m);
  173           }
  174       }
  175   
  176       // Query Operations
  177   
  178       /**
  179        * Returns the number of key-value mappings in this map.
  180        *
  181        * @return the number of key-value mappings in this map
  182        */
  183       public int size() {
  184           return size;
  185       }
  186   
  187       /**
  188        * Returns <tt>true</tt> if this map maps one or more keys to the
  189        * specified value.
  190        *
  191        * @param value the value whose presence in this map is to be tested
  192        * @return <tt>true</tt> if this map maps one or more keys to this value
  193        */
  194       public boolean containsValue(Object value) {
  195           value = maskNull(value);
  196   
  197           for (Object val : vals)
  198               if (value.equals(val))
  199                   return true;
  200   
  201           return false;
  202       }
  203   
  204       /**
  205        * Returns <tt>true</tt> if this map contains a mapping for the specified
  206        * key.
  207        *
  208        * @param key the key whose presence in this map is to be tested
  209        * @return <tt>true</tt> if this map contains a mapping for the specified
  210        *            key
  211        */
  212       public boolean containsKey(Object key) {
  213           return isValidKey(key) && vals[((Enum)key).ordinal()] != null;
  214       }
  215   
  216       private boolean containsMapping(Object key, Object value) {
  217           return isValidKey(key) &&
  218               maskNull(value).equals(vals[((Enum)key).ordinal()]);
  219       }
  220   
  221       /**
  222        * Returns the value to which the specified key is mapped,
  223        * or {@code null} if this map contains no mapping for the key.
  224        *
  225        * <p>More formally, if this map contains a mapping from a key
  226        * {@code k} to a value {@code v} such that {@code (key == k)},
  227        * then this method returns {@code v}; otherwise it returns
  228        * {@code null}.  (There can be at most one such mapping.)
  229        *
  230        * <p>A return value of {@code null} does not <i>necessarily</i>
  231        * indicate that the map contains no mapping for the key; it's also
  232        * possible that the map explicitly maps the key to {@code null}.
  233        * The {@link #containsKey containsKey} operation may be used to
  234        * distinguish these two cases.
  235        */
  236       public V get(Object key) {
  237           return (isValidKey(key) ?
  238                   unmaskNull(vals[((Enum)key).ordinal()]) : null);
  239       }
  240   
  241       // Modification Operations
  242   
  243       /**
  244        * Associates the specified value with the specified key in this map.
  245        * If the map previously contained a mapping for this key, the old
  246        * value is replaced.
  247        *
  248        * @param key the key with which the specified value is to be associated
  249        * @param value the value to be associated with the specified key
  250        *
  251        * @return the previous value associated with specified key, or
  252        *     <tt>null</tt> if there was no mapping for key.  (A <tt>null</tt>
  253        *     return can also indicate that the map previously associated
  254        *     <tt>null</tt> with the specified key.)
  255        * @throws NullPointerException if the specified key is null
  256        */
  257       public V put(K key, V value) {
  258           typeCheck(key);
  259   
  260           int index = key.ordinal();
  261           Object oldValue = vals[index];
  262           vals[index] = maskNull(value);
  263           if (oldValue == null)
  264               size++;
  265           return unmaskNull(oldValue);
  266       }
  267   
  268       /**
  269        * Removes the mapping for this key from this map if present.
  270        *
  271        * @param key the key whose mapping is to be removed from the map
  272        * @return the previous value associated with specified key, or
  273        *     <tt>null</tt> if there was no entry for key.  (A <tt>null</tt>
  274        *     return can also indicate that the map previously associated
  275        *     <tt>null</tt> with the specified key.)
  276        */
  277       public V remove(Object key) {
  278           if (!isValidKey(key))
  279               return null;
  280           int index = ((Enum)key).ordinal();
  281           Object oldValue = vals[index];
  282           vals[index] = null;
  283           if (oldValue != null)
  284               size--;
  285           return unmaskNull(oldValue);
  286       }
  287   
  288       private boolean removeMapping(Object key, Object value) {
  289           if (!isValidKey(key))
  290               return false;
  291           int index = ((Enum)key).ordinal();
  292           if (maskNull(value).equals(vals[index])) {
  293               vals[index] = null;
  294               size--;
  295               return true;
  296           }
  297           return false;
  298       }
  299   
  300       /**
  301        * Returns true if key is of the proper type to be a key in this
  302        * enum map.
  303        */
  304       private boolean isValidKey(Object key) {
  305           if (key == null)
  306               return false;
  307   
  308           // Cheaper than instanceof Enum followed by getDeclaringClass
  309           Class keyClass = key.getClass();
  310           return keyClass == keyType || keyClass.getSuperclass() == keyType;
  311       }
  312   
  313       // Bulk Operations
  314   
  315       /**
  316        * Copies all of the mappings from the specified map to this map.
  317        * These mappings will replace any mappings that this map had for
  318        * any of the keys currently in the specified map.
  319        *
  320        * @param m the mappings to be stored in this map
  321        * @throws NullPointerException the specified map is null, or if
  322        *     one or more keys in the specified map are null
  323        */
  324       public void putAll(Map<? extends K, ? extends V> m) {
  325           if (m instanceof EnumMap) {
  326               EnumMap<? extends K, ? extends V> em =
  327                   (EnumMap<? extends K, ? extends V>)m;
  328               if (em.keyType != keyType) {
  329                   if (em.isEmpty())
  330                       return;
  331                   throw new ClassCastException(em.keyType + " != " + keyType);
  332               }
  333   
  334               for (int i = 0; i < keyUniverse.length; i++) {
  335                   Object emValue = em.vals[i];
  336                   if (emValue != null) {
  337                       if (vals[i] == null)
  338                           size++;
  339                       vals[i] = emValue;
  340                   }
  341               }
  342           } else {
  343               super.putAll(m);
  344           }
  345       }
  346   
  347       /**
  348        * Removes all mappings from this map.
  349        */
  350       public void clear() {
  351           Arrays.fill(vals, null);
  352           size = 0;
  353       }
  354   
  355       // Views
  356   
  357       /**
  358        * This field is initialized to contain an instance of the entry set
  359        * view the first time this view is requested.  The view is stateless,
  360        * so there's no reason to create more than one.
  361        */
  362       private transient Set<Map.Entry<K,V>> entrySet = null;
  363   
  364       /**
  365        * Returns a {@link Set} view of the keys contained in this map.
  366        * The returned set obeys the general contract outlined in
  367        * {@link Map#keySet()}.  The set's iterator will return the keys
  368        * in their natural order (the order in which the enum constants
  369        * are declared).
  370        *
  371        * @return a set view of the keys contained in this enum map
  372        */
  373       public Set<K> keySet() {
  374           Set<K> ks = keySet;
  375           if (ks != null)
  376               return ks;
  377           else
  378               return keySet = new KeySet();
  379       }
  380   
  381       private class KeySet extends AbstractSet<K> {
  382           public Iterator<K> iterator() {
  383               return new KeyIterator();
  384           }
  385           public int size() {
  386               return size;
  387           }
  388           public boolean contains(Object o) {
  389               return containsKey(o);
  390           }
  391           public boolean remove(Object o) {
  392               int oldSize = size;
  393               EnumMap.this.remove(o);
  394               return size != oldSize;
  395           }
  396           public void clear() {
  397               EnumMap.this.clear();
  398           }
  399       }
  400   
  401       /**
  402        * Returns a {@link Collection} view of the values contained in this map.
  403        * The returned collection obeys the general contract outlined in
  404        * {@link Map#values()}.  The collection's iterator will return the
  405        * values in the order their corresponding keys appear in map,
  406        * which is their natural order (the order in which the enum constants
  407        * are declared).
  408        *
  409        * @return a collection view of the values contained in this map
  410        */
  411       public Collection<V> values() {
  412           Collection<V> vs = values;
  413           if (vs != null)
  414               return vs;
  415           else
  416               return values = new Values();
  417       }
  418   
  419       private class Values extends AbstractCollection<V> {
  420           public Iterator<V> iterator() {
  421               return new ValueIterator();
  422           }
  423           public int size() {
  424               return size;
  425           }
  426           public boolean contains(Object o) {
  427               return containsValue(o);
  428           }
  429           public boolean remove(Object o) {
  430               o = maskNull(o);
  431   
  432               for (int i = 0; i < vals.length; i++) {
  433                   if (o.equals(vals[i])) {
  434                       vals[i] = null;
  435                       size--;
  436                       return true;
  437                   }
  438               }
  439               return false;
  440           }
  441           public void clear() {
  442               EnumMap.this.clear();
  443           }
  444       }
  445   
  446       /**
  447        * Returns a {@link Set} view of the mappings contained in this map.
  448        * The returned set obeys the general contract outlined in
  449        * {@link Map#keySet()}.  The set's iterator will return the
  450        * mappings in the order their keys appear in map, which is their
  451        * natural order (the order in which the enum constants are declared).
  452        *
  453        * @return a set view of the mappings contained in this enum map
  454        */
  455       public Set<Map.Entry<K,V>> entrySet() {
  456           Set<Map.Entry<K,V>> es = entrySet;
  457           if (es != null)
  458               return es;
  459           else
  460               return entrySet = new EntrySet();
  461       }
  462   
  463       private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
  464           public Iterator<Map.Entry<K,V>> iterator() {
  465               return new EntryIterator();
  466           }
  467           public boolean contains(Object o) {
  468               if (!(o instanceof Map.Entry))
  469                   return false;
  470               Map.Entry entry = (Map.Entry)o;
  471               return containsMapping(entry.getKey(), entry.getValue());
  472           }
  473           public boolean remove(Object o) {
  474               if (!(o instanceof Map.Entry))
  475                   return false;
  476               Map.Entry entry = (Map.Entry)o;
  477               return removeMapping(entry.getKey(), entry.getValue());
  478           }
  479           public int size() {
  480               return size;
  481           }
  482           public void clear() {
  483               EnumMap.this.clear();
  484           }
  485           public Object[] toArray() {
  486               return fillEntryArray(new Object[size]);
  487           }
  488           @SuppressWarnings("unchecked")
  489           public <T> T[] toArray(T[] a) {
  490               int size = size();
  491               if (a.length < size)
  492                   a = (T[])java.lang.reflect.Array
  493                       .newInstance(a.getClass().getComponentType(), size);
  494               if (a.length > size)
  495                   a[size] = null;
  496               return (T[]) fillEntryArray(a);
  497           }
  498           private Object[] fillEntryArray(Object[] a) {
  499               int j = 0;
  500               for (int i = 0; i < vals.length; i++)
  501                   if (vals[i] != null)
  502                       a[j++] = new AbstractMap.SimpleEntry<K,V>(
  503                           keyUniverse[i], unmaskNull(vals[i]));
  504               return a;
  505           }
  506       }
  507   
  508       private abstract class EnumMapIterator<T> implements Iterator<T> {
  509           // Lower bound on index of next element to return
  510           int index = 0;
  511   
  512           // Index of last returned element, or -1 if none
  513           int lastReturnedIndex = -1;
  514   
  515           public boolean hasNext() {
  516               while (index < vals.length && vals[index] == null)
  517                   index++;
  518               return index != vals.length;
  519           }
  520   
  521           public void remove() {
  522               checkLastReturnedIndex();
  523   
  524               if (vals[lastReturnedIndex] != null) {
  525                   vals[lastReturnedIndex] = null;
  526                   size--;
  527               }
  528               lastReturnedIndex = -1;
  529           }
  530   
  531           private void checkLastReturnedIndex() {
  532               if (lastReturnedIndex < 0)
  533                   throw new IllegalStateException();
  534           }
  535       }
  536   
  537       private class KeyIterator extends EnumMapIterator<K> {
  538           public K next() {
  539               if (!hasNext())
  540                   throw new NoSuchElementException();
  541               lastReturnedIndex = index++;
  542               return keyUniverse[lastReturnedIndex];
  543           }
  544       }
  545   
  546       private class ValueIterator extends EnumMapIterator<V> {
  547           public V next() {
  548               if (!hasNext())
  549                   throw new NoSuchElementException();
  550               lastReturnedIndex = index++;
  551               return unmaskNull(vals[lastReturnedIndex]);
  552           }
  553       }
  554   
  555       /**
  556        * Since we don't use Entry objects, we use the Iterator itself as entry.
  557        */
  558       private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>>
  559           implements Map.Entry<K,V>
  560       {
  561           public Map.Entry<K,V> next() {
  562               if (!hasNext())
  563                   throw new NoSuchElementException();
  564               lastReturnedIndex = index++;
  565               return this;
  566           }
  567   
  568           public K getKey() {
  569               checkLastReturnedIndexForEntryUse();
  570               return keyUniverse[lastReturnedIndex];
  571           }
  572   
  573           public V getValue() {
  574               checkLastReturnedIndexForEntryUse();
  575               return unmaskNull(vals[lastReturnedIndex]);
  576           }
  577   
  578           public V setValue(V value) {
  579               checkLastReturnedIndexForEntryUse();
  580               V oldValue = unmaskNull(vals[lastReturnedIndex]);
  581               vals[lastReturnedIndex] = maskNull(value);
  582               return oldValue;
  583           }
  584   
  585           public boolean equals(Object o) {
  586               if (lastReturnedIndex < 0)
  587                   return o == this;
  588   
  589               if (!(o instanceof Map.Entry))
  590                   return false;
  591               Map.Entry e = (Map.Entry)o;
  592               V ourValue = unmaskNull(vals[lastReturnedIndex]);
  593               Object hisValue = e.getValue();
  594               return e.getKey() == keyUniverse[lastReturnedIndex] &&
  595                   (ourValue == hisValue ||
  596                    (ourValue != null && ourValue.equals(hisValue)));
  597           }
  598   
  599           public int hashCode() {
  600               if (lastReturnedIndex < 0)
  601                   return super.hashCode();
  602   
  603               Object value = vals[lastReturnedIndex];
  604               return keyUniverse[lastReturnedIndex].hashCode()
  605                   ^ (value == NULL ? 0 : value.hashCode());
  606           }
  607   
  608           public String toString() {
  609               if (lastReturnedIndex < 0)
  610                   return super.toString();
  611   
  612               return keyUniverse[lastReturnedIndex] + "="
  613                   + unmaskNull(vals[lastReturnedIndex]);
  614           }
  615   
  616           private void checkLastReturnedIndexForEntryUse() {
  617               if (lastReturnedIndex < 0)
  618                   throw new IllegalStateException("Entry was removed");
  619           }
  620       }
  621   
  622       // Comparison and hashing
  623   
  624       /**
  625        * Compares the specified object with this map for equality.  Returns
  626        * <tt>true</tt> if the given object is also a map and the two maps
  627        * represent the same mappings, as specified in the {@link
  628        * Map#equals(Object)} contract.
  629        *
  630        * @param o the object to be compared for equality with this map
  631        * @return <tt>true</tt> if the specified object is equal to this map
  632        */
  633       public boolean equals(Object o) {
  634           if (!(o instanceof EnumMap))
  635               return super.equals(o);
  636   
  637           EnumMap em = (EnumMap)o;
  638           if (em.keyType != keyType)
  639               return size == 0 && em.size == 0;
  640   
  641           // Key types match, compare each value
  642           for (int i = 0; i < keyUniverse.length; i++) {
  643               Object ourValue =    vals[i];
  644               Object hisValue = em.vals[i];
  645               if (hisValue != ourValue &&
  646                   (hisValue == null || !hisValue.equals(ourValue)))
  647                   return false;
  648           }
  649           return true;
  650       }
  651   
  652       /**
  653        * Returns a shallow copy of this enum map.  (The values themselves
  654        * are not cloned.
  655        *
  656        * @return a shallow copy of this enum map
  657        */
  658       public EnumMap<K, V> clone() {
  659           EnumMap<K, V> result = null;
  660           try {
  661               result = (EnumMap<K, V>) super.clone();
  662           } catch(CloneNotSupportedException e) {
  663               throw new AssertionError();
  664           }
  665           result.vals = result.vals.clone();
  666           return result;
  667       }
  668   
  669       /**
  670        * Throws an exception if e is not of the correct type for this enum set.
  671        */
  672       private void typeCheck(K key) {
  673           Class keyClass = key.getClass();
  674           if (keyClass != keyType && keyClass.getSuperclass() != keyType)
  675               throw new ClassCastException(keyClass + " != " + keyType);
  676       }
  677   
  678       /**
  679        * Returns all of the values comprising K.
  680        * The result is uncloned, cached, and shared by all callers.
  681        */
  682       private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
  683           return SharedSecrets.getJavaLangAccess()
  684                                           .getEnumConstantsShared(keyType);
  685       }
  686   
  687       private static final long serialVersionUID = 458661240069192865L;
  688   
  689       /**
  690        * Save the state of the <tt>EnumMap</tt> instance to a stream (i.e.,
  691        * serialize it).
  692        *
  693        * @serialData The <i>size</i> of the enum map (the number of key-value
  694        *             mappings) is emitted (int), followed by the key (Object)
  695        *             and value (Object) for each key-value mapping represented
  696        *             by the enum map.
  697        */
  698       private void writeObject(java.io.ObjectOutputStream s)
  699           throws java.io.IOException
  700       {
  701           // Write out the key type and any hidden stuff
  702           s.defaultWriteObject();
  703   
  704           // Write out size (number of Mappings)
  705           s.writeInt(size);
  706   
  707           // Write out keys and values (alternating)
  708           for (Map.Entry<K,V> e :  entrySet()) {
  709               s.writeObject(e.getKey());
  710               s.writeObject(e.getValue());
  711           }
  712       }
  713   
  714       /**
  715        * Reconstitute the <tt>EnumMap</tt> instance from a stream (i.e.,
  716        * deserialize it).
  717        */
  718       private void readObject(java.io.ObjectInputStream s)
  719           throws java.io.IOException, ClassNotFoundException
  720       {
  721           // Read in the key type and any hidden stuff
  722           s.defaultReadObject();
  723   
  724           keyUniverse = getKeyUniverse(keyType);
  725           vals = new Object[keyUniverse.length];
  726   
  727           // Read in size (number of Mappings)
  728           int size = s.readInt();
  729   
  730           // Read the keys and values, and put the mappings in the HashMap
  731           for (int i = 0; i < size; i++) {
  732               K key = (K) s.readObject();
  733               V value = (V) s.readObject();
  734               put(key, value);
  735           }
  736       }
  737   }

Save This Page
Home » openjdk-7 » java » util » [javadoc | source]