001/* 002 * Copyright (C) 2008 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.collect; 018 019import static com.google.common.base.Preconditions.checkNotNull; 020 021import com.google.common.annotations.GwtCompatible; 022 023import java.util.Collection; 024import java.util.Map; 025 026/** 027 * An immutable {@link BiMap} with reliable user-specified iteration order. Does 028 * not permit null keys or values. An {@code ImmutableBiMap} and its inverse 029 * have the same iteration ordering. 030 * 031 * <p>An instance of {@code ImmutableBiMap} contains its own data and will 032 * <i>never</i> change. {@code ImmutableBiMap} is convenient for 033 * {@code public static final} maps ("constant maps") and also lets you easily 034 * make a "defensive copy" of a bimap provided to your class by a caller. 035 * 036 * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as 037 * it has no public or protected constructors. Thus, instances of this class are 038 * guaranteed to be immutable. 039 * 040 * @author Jared Levy 041 * @since 2.0 (imported from Google Collections Library) 042 */ 043@GwtCompatible(serializable = true, emulated = true) 044public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> 045 implements BiMap<K, V> { 046 047 /** 048 * Returns the empty bimap. 049 */ 050 // Casting to any type is safe because the set will never hold any elements. 051 @SuppressWarnings("unchecked") 052 public static <K, V> ImmutableBiMap<K, V> of() { 053 return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE; 054 } 055 056 /** 057 * Returns an immutable bimap containing a single entry. 058 */ 059 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) { 060 checkNotNull(k1, "null key in entry: null=%s", v1); 061 checkNotNull(v1, "null value in entry: %s=null", k1); 062 return new SingletonImmutableBiMap<K, V>(k1, v1); 063 } 064 065 /** 066 * Returns an immutable map containing the given entries, in order. 067 * 068 * @throws IllegalArgumentException if duplicate keys or values are added 069 */ 070 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) { 071 return new Builder<K, V>() 072 .put(k1, v1) 073 .put(k2, v2) 074 .build(); 075 } 076 077 /** 078 * Returns an immutable map containing the given entries, in order. 079 * 080 * @throws IllegalArgumentException if duplicate keys or values are added 081 */ 082 public static <K, V> ImmutableBiMap<K, V> of( 083 K k1, V v1, K k2, V v2, K k3, V v3) { 084 return new Builder<K, V>() 085 .put(k1, v1) 086 .put(k2, v2) 087 .put(k3, v3) 088 .build(); 089 } 090 091 /** 092 * Returns an immutable map containing the given entries, in order. 093 * 094 * @throws IllegalArgumentException if duplicate keys or values are added 095 */ 096 public static <K, V> ImmutableBiMap<K, V> of( 097 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 098 return new Builder<K, V>() 099 .put(k1, v1) 100 .put(k2, v2) 101 .put(k3, v3) 102 .put(k4, v4) 103 .build(); 104 } 105 106 /** 107 * Returns an immutable map containing the given entries, in order. 108 * 109 * @throws IllegalArgumentException if duplicate keys or values are added 110 */ 111 public static <K, V> ImmutableBiMap<K, V> of( 112 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 113 return new Builder<K, V>() 114 .put(k1, v1) 115 .put(k2, v2) 116 .put(k3, v3) 117 .put(k4, v4) 118 .put(k5, v5) 119 .build(); 120 } 121 122 // looking for of() with > 5 entries? Use the builder instead. 123 124 /** 125 * Returns a new builder. The generated builder is equivalent to the builder 126 * created by the {@link Builder} constructor. 127 */ 128 public static <K, V> Builder<K, V> builder() { 129 return new Builder<K, V>(); 130 } 131 132 /** 133 * A builder for creating immutable bimap instances, especially {@code public 134 * static final} bimaps ("constant bimaps"). Example: <pre> {@code 135 * 136 * static final ImmutableBiMap<String, Integer> WORD_TO_INT = 137 * new ImmutableBiMap.Builder<String, Integer>() 138 * .put("one", 1) 139 * .put("two", 2) 140 * .put("three", 3) 141 * .build();}</pre> 142 * 143 * For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods 144 * are even more convenient. 145 * 146 * <p>Builder instances can be reused - it is safe to call {@link #build} 147 * multiple times to build multiple bimaps in series. Each bimap is a superset 148 * of the bimaps created before it. 149 * 150 * @since 2.0 (imported from Google Collections Library) 151 */ 152 public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> { 153 154 /** 155 * Creates a new builder. The returned builder is equivalent to the builder 156 * generated by {@link ImmutableBiMap#builder}. 157 */ 158 public Builder() {} 159 160 /** 161 * Associates {@code key} with {@code value} in the built bimap. Duplicate 162 * keys or values are not allowed, and will cause {@link #build} to fail. 163 */ 164 @Override public Builder<K, V> put(K key, V value) { 165 super.put(key, value); 166 return this; 167 } 168 169 /** 170 * Associates all of the given map's keys and values in the built bimap. 171 * Duplicate keys or values are not allowed, and will cause {@link #build} 172 * to fail. 173 * 174 * @throws NullPointerException if any key or value in {@code map} is null 175 */ 176 @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) { 177 super.putAll(map); 178 return this; 179 } 180 181 /** 182 * Returns a newly-created immutable bimap. 183 * 184 * @throws IllegalArgumentException if duplicate keys or values were added 185 */ 186 @Override public ImmutableBiMap<K, V> build() { 187 return fromEntries(entries); 188 } 189 } 190 191 /** 192 * Returns an immutable bimap containing the same entries as {@code map}. If 193 * {@code map} somehow contains entries with duplicate keys (for example, if 194 * it is a {@code SortedMap} whose comparator is not <i>consistent with 195 * equals</i>), the results of this method are undefined. 196 * 197 * <p>Despite the method name, this method attempts to avoid actually copying 198 * the data when it is safe to do so. The exact circumstances under which a 199 * copy will or will not be performed are undocumented and subject to change. 200 * 201 * @throws IllegalArgumentException if two keys have the same value 202 * @throws NullPointerException if any key or value in {@code map} is null 203 */ 204 public static <K, V> ImmutableBiMap<K, V> copyOf( 205 Map<? extends K, ? extends V> map) { 206 if (map instanceof ImmutableBiMap) { 207 @SuppressWarnings("unchecked") // safe since map is not writable 208 ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map; 209 // TODO(user): if we need to make a copy of a BiMap because the 210 // forward map is a view, don't make a copy of the non-view delegate map 211 if (!bimap.isPartialView()) { 212 return bimap; 213 } 214 } 215 216 return fromEntries(ImmutableList.copyOf(map.entrySet())); 217 } 218 219 static <K, V> ImmutableBiMap<K, V> fromEntries( 220 Collection<? extends Entry<? extends K, ? extends V>> entries) { 221 switch (entries.size()) { 222 case 0: 223 return of(); 224 case 1: { 225 Entry<? extends K, ? extends V> entry = Iterables.getOnlyElement(entries); 226 return new SingletonImmutableBiMap<K, V>(entry.getKey(), entry.getValue()); 227 } 228 default: 229 return new RegularImmutableBiMap<K, V>(entries); 230 } 231 } 232 233 ImmutableBiMap() {} 234 235 /** 236 * {@inheritDoc} 237 * 238 * <p>The inverse of an {@code ImmutableBiMap} is another 239 * {@code ImmutableBiMap}. 240 */ 241 @Override 242 public abstract ImmutableBiMap<V, K> inverse(); 243 244 /** 245 * Returns an immutable set of the values in this map. The values are in the 246 * same order as the parameters used to build this map. 247 */ 248 @Override public ImmutableSet<V> values() { 249 return inverse().keySet(); 250 } 251 252 /** 253 * Guaranteed to throw an exception and leave the bimap unmodified. 254 * 255 * @throws UnsupportedOperationException always 256 * @deprecated Unsupported operation. 257 */ 258 @Deprecated 259 @Override 260 public V forcePut(K key, V value) { 261 throw new UnsupportedOperationException(); 262 } 263 264 /** 265 * Serialized type for all ImmutableBiMap instances. It captures the logical 266 * contents and they are reconstructed using public factory methods. This 267 * ensures that the implementation types remain as implementation details. 268 * 269 * Since the bimap is immutable, ImmutableBiMap doesn't require special logic 270 * for keeping the bimap and its inverse in sync during serialization, the way 271 * AbstractBiMap does. 272 */ 273 private static class SerializedForm extends ImmutableMap.SerializedForm { 274 SerializedForm(ImmutableBiMap<?, ?> bimap) { 275 super(bimap); 276 } 277 @Override Object readResolve() { 278 Builder<Object, Object> builder = new Builder<Object, Object>(); 279 return createMap(builder); 280 } 281 private static final long serialVersionUID = 0; 282 } 283 284 @Override Object writeReplace() { 285 return new SerializedForm(this); 286 } 287}