Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * 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 com.google.common.collect;
     18 
     19 import com.google.common.annotations.GwtCompatible;
     20 import com.google.common.annotations.GwtIncompatible;
     21 
     22 import java.io.IOException;
     23 import java.io.ObjectInputStream;
     24 import java.io.ObjectOutputStream;
     25 import java.util.EnumMap;
     26 import java.util.HashMap;
     27 import java.util.Map;
     28 
     29 import javax.annotation.Nullable;
     30 
     31 /**
     32  * A {@code BiMap} backed by an {@code EnumMap} instance for keys-to-values, and
     33  * a {@code HashMap} instance for values-to-keys. Null keys are not permitted,
     34  * but null values are. An {@code EnumHashBiMap} and its inverse are both
     35  * serializable.
     36  *
     37  * @author Mike Bostock
     38  * @since 2.0 (imported from Google Collections Library)
     39  */
     40 @GwtCompatible(emulated = true)
     41 public final class EnumHashBiMap<K extends Enum<K>, V>
     42     extends AbstractBiMap<K, V> {
     43   private transient Class<K> keyType;
     44 
     45   /**
     46    * Returns a new, empty {@code EnumHashBiMap} using the specified key type.
     47    *
     48    * @param keyType the key type
     49    */
     50   public static <K extends Enum<K>, V> EnumHashBiMap<K, V>
     51       create(Class<K> keyType) {
     52     return new EnumHashBiMap<K, V>(keyType);
     53   }
     54 
     55   /**
     56    * Constructs a new bimap with the same mappings as the specified map. If the
     57    * specified map is an {@code EnumHashBiMap} or an {@link EnumBiMap}, the new
     58    * bimap has the same key type as the input bimap. Otherwise, the specified
     59    * map must contain at least one mapping, in order to determine the key type.
     60    *
     61    * @param map the map whose mappings are to be placed in this map
     62    * @throws IllegalArgumentException if map is not an {@code EnumBiMap} or an
     63    *     {@code EnumHashBiMap} instance and contains no mappings
     64    */
     65   public static <K extends Enum<K>, V> EnumHashBiMap<K, V>
     66       create(Map<K, ? extends V> map) {
     67     EnumHashBiMap<K, V> bimap = create(EnumBiMap.inferKeyType(map));
     68     bimap.putAll(map);
     69     return bimap;
     70   }
     71 
     72   private EnumHashBiMap(Class<K> keyType) {
     73     super(WellBehavedMap.wrap(
     74         new EnumMap<K, V>(keyType)),
     75         Maps.<V, K>newHashMapWithExpectedSize(
     76             keyType.getEnumConstants().length));
     77     this.keyType = keyType;
     78   }
     79 
     80   // Overriding these two methods to show that values may be null (but not keys)
     81 
     82   @Override public V put(K key, @Nullable V value) {
     83     return super.put(key, value);
     84   }
     85 
     86   @Override public V forcePut(K key, @Nullable V value) {
     87     return super.forcePut(key, value);
     88   }
     89 
     90   /** Returns the associated key type. */
     91   public Class<K> keyType() {
     92     return keyType;
     93   }
     94 
     95   /**
     96    * @serialData the key class, number of entries, first key, first value,
     97    *     second key, second value, and so on.
     98    */
     99   @GwtIncompatible("java.io.ObjectOutputStream")
    100   private void writeObject(ObjectOutputStream stream) throws IOException {
    101     stream.defaultWriteObject();
    102     stream.writeObject(keyType);
    103     Serialization.writeMap(this, stream);
    104   }
    105 
    106   @SuppressWarnings("unchecked") // reading field populated by writeObject
    107   @GwtIncompatible("java.io.ObjectInputStream")
    108   private void readObject(ObjectInputStream stream)
    109       throws IOException, ClassNotFoundException {
    110     stream.defaultReadObject();
    111     keyType = (Class<K>) stream.readObject();
    112     setDelegates(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
    113         new HashMap<V, K>(keyType.getEnumConstants().length * 3 / 2));
    114     Serialization.populateMap(this, stream);
    115   }
    116 
    117   @GwtIncompatible("only needed in emulated source.")
    118   private static final long serialVersionUID = 0;
    119 }
    120