• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.errorprone.annotations.CanIgnoreReturnValue;
24 import java.io.IOException;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.util.EnumMap;
28 import java.util.HashMap;
29 import java.util.Map;
30 import javax.annotation.CheckForNull;
31 import org.checkerframework.checker.nullness.qual.Nullable;
32 
33 /**
34  * A {@code BiMap} backed by an {@code EnumMap} instance for keys-to-values, and a {@code HashMap}
35  * instance for values-to-keys. Null keys are not permitted, but null values are. An {@code
36  * EnumHashBiMap} and its inverse are both serializable.
37  *
38  * <p>See the Guava User Guide article on <a href=
39  * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#bimap"> {@code BiMap}</a>.
40  *
41  * @author Mike Bostock
42  * @since 2.0
43  */
44 @GwtCompatible(emulated = true)
45 @ElementTypesAreNonnullByDefault
46 public final class EnumHashBiMap<K extends Enum<K>, V extends @Nullable Object>
47     extends AbstractBiMap<K, V> {
48   private transient Class<K> keyType;
49 
50   /**
51    * Returns a new, empty {@code EnumHashBiMap} using the specified key type.
52    *
53    * @param keyType the key type
54    */
create( Class<K> keyType)55   public static <K extends Enum<K>, V extends @Nullable Object> EnumHashBiMap<K, V> create(
56       Class<K> keyType) {
57     return new EnumHashBiMap<>(keyType);
58   }
59 
60   /**
61    * Constructs a new bimap with the same mappings as the specified map. If the specified map is an
62    * {@code EnumHashBiMap} or an {@link EnumBiMap}, the new bimap has the same key type as the input
63    * bimap. Otherwise, the specified map must contain at least one mapping, in order to determine
64    * the key type.
65    *
66    * @param map the map whose mappings are to be placed in this map
67    * @throws IllegalArgumentException if map is not an {@code EnumBiMap} or an {@code EnumHashBiMap}
68    *     instance and contains no mappings
69    */
create( Map<K, ? extends V> map)70   public static <K extends Enum<K>, V extends @Nullable Object> EnumHashBiMap<K, V> create(
71       Map<K, ? extends V> map) {
72     EnumHashBiMap<K, V> bimap = create(EnumBiMap.inferKeyType(map));
73     bimap.putAll(map);
74     return bimap;
75   }
76 
EnumHashBiMap(Class<K> keyType)77   private EnumHashBiMap(Class<K> keyType) {
78     super(
79         new EnumMap<K, V>(keyType),
80         Maps.<V, K>newHashMapWithExpectedSize(keyType.getEnumConstants().length));
81     this.keyType = keyType;
82   }
83 
84   // Overriding these 3 methods to show that values may be null (but not keys)
85 
86   @Override
checkKey(K key)87   K checkKey(K key) {
88     return checkNotNull(key);
89   }
90 
91   @CanIgnoreReturnValue
92   @Override
93   @SuppressWarnings("RedundantOverride") // b/192446478: RedundantOverride ignores some annotations.
94   // TODO(b/192446998): Remove this override after tools understand nullness better.
95   @CheckForNull
put(K key, @ParametricNullness V value)96   public V put(K key, @ParametricNullness V value) {
97     return super.put(key, value);
98   }
99 
100   @CanIgnoreReturnValue
101   @Override
102   @SuppressWarnings("RedundantOverride") // b/192446478: RedundantOverride ignores some annotations.
103   // TODO(b/192446998): Remove this override after tools understand nullness better.
104   @CheckForNull
forcePut(K key, @ParametricNullness V value)105   public V forcePut(K key, @ParametricNullness V value) {
106     return super.forcePut(key, value);
107   }
108 
109   /** Returns the associated key type. */
keyType()110   public Class<K> keyType() {
111     return keyType;
112   }
113 
114   /**
115    * @serialData the key class, number of entries, first key, first value, second key, second value,
116    *     and so on.
117    */
118   @GwtIncompatible // java.io.ObjectOutputStream
writeObject(ObjectOutputStream stream)119   private void writeObject(ObjectOutputStream stream) throws IOException {
120     stream.defaultWriteObject();
121     stream.writeObject(keyType);
122     Serialization.writeMap(this, stream);
123   }
124 
125   @SuppressWarnings("unchecked") // reading field populated by writeObject
126   @GwtIncompatible // java.io.ObjectInputStream
readObject(ObjectInputStream stream)127   private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
128     stream.defaultReadObject();
129     keyType = (Class<K>) stream.readObject();
130     setDelegates(
131         new EnumMap<K, V>(keyType), new HashMap<V, K>(keyType.getEnumConstants().length * 3 / 2));
132     Serialization.populateMap(this, stream);
133   }
134 
135   @GwtIncompatible // only needed in emulated source.
136   private static final long serialVersionUID = 0;
137 }
138