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