EnumHashBiMap.java revision 090f9b4c879985bc747c214f82c62471e60c7742
1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/* 2090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Copyright (C) 2007 Google Inc. 3090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 4090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * you may not use this file except in compliance with the License. 6090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * You may obtain a copy of the License at 7090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 8090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 10090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * See the License for the specific language governing permissions and 14090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * limitations under the License. 15090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 16090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 17090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpackage com.google.common.collect; 18090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 19090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.IOException; 20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectInputStream; 21090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectOutputStream; 22090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.EnumMap; 23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.HashMap; 24090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Map; 25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport javax.annotation.Nullable; 27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/** 29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * A {@code BiMap} backed by an {@code EnumMap} instance for keys-to-values, and 30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * a {@code HashMap} instance for values-to-keys. Null keys are not permitted, 31090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * but null values are. An {@code EnumHashBiMap} and its inverse are both 32090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * serializable. 33090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 34090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Mike Bostock 35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpublic final class EnumHashBiMap<K extends Enum<K>, V> 37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson extends AbstractBiMap<K, V> { 38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Class<K> keyType; 39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Returns a new, empty {@code EnumHashBiMap} using the specified key type. 42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @param keyType the key type 44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public static <K extends Enum<K>, V> EnumHashBiMap<K, V> 46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson create(Class<K> keyType) { 47090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new EnumHashBiMap<K, V>(keyType); 48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Constructs a new bimap with the same mappings as the specified map. If the 52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * specified map is an {@code EnumHashBiMap} or an {@link EnumBiMap}, the new 53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * bimap has the same key type as the input bimap. Otherwise, the specified 54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * map must contain at least one mapping, in order to determine the key type. 55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @param map the map whose mappings are to be placed in this map 57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @throws IllegalArgumentException if map is not an {@code EnumBiMap} or an 58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * {@code EnumHashBiMap} instance and contains no mappings 59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public static <K extends Enum<K>, V> EnumHashBiMap<K, V> 61090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson create(Map<K, ? extends V> map) { 62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson EnumHashBiMap<K, V> bimap = create(EnumBiMap.inferKeyType(map)); 63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson bimap.putAll(map); 64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return bimap; 65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 67090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private EnumHashBiMap(Class<K> keyType) { 68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson super(new EnumMap<K, V>(keyType), Maps.<V, K>newHashMapWithExpectedSize( 69090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson keyType.getEnumConstants().length)); 70090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson this.keyType = keyType; 71090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Overriding these two methods to show that values may be null (but not keys) 74090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public V put(K key, @Nullable V value) { 76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return super.put(key, value); 77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 79090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public V forcePut(K key, @Nullable V value) { 80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return super.forcePut(key, value); 81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** Returns the associated key type. */ 84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public Class<K> keyType() { 85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return keyType; 86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @serialData the key class, number of entries, first key, first value, 90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * second key, second value, and so on. 91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void writeObject(ObjectOutputStream stream) throws IOException { 93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.defaultWriteObject(); 94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeObject(keyType); 95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Serialization.writeMap(this, stream); 96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @SuppressWarnings("unchecked") // reading field populated by writeObject 99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void readObject(ObjectInputStream stream) 100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException, ClassNotFoundException { 101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.defaultReadObject(); 102090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson keyType = (Class<K>) stream.readObject(); 103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson setDelegates(new EnumMap<K, V>(keyType), 104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson new HashMap<V, K>(keyType.getEnumConstants().length * 3 / 2)); 105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Serialization.populateMap(this, stream); 106090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 107090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private static final long serialVersionUID = 0; 109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson} 110