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.collect.CollectPreconditions.checkEntryNotNull; 020import static com.google.common.collect.CollectPreconditions.checkNonnegative; 021 022import com.google.common.annotations.Beta; 023import com.google.common.annotations.GwtCompatible; 024import com.google.errorprone.annotations.CanIgnoreReturnValue; 025import java.util.Collection; 026import java.util.Comparator; 027import java.util.Map; 028 029/** 030 * A {@link BiMap} whose contents will never change, with many other important properties detailed 031 * at {@link ImmutableCollection}. 032 * 033 * @author Jared Levy 034 * @since 2.0 035 */ 036@GwtCompatible(serializable = true, emulated = true) 037public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> { 038 039 /** Returns the empty bimap. */ 040 // Casting to any type is safe because the set will never hold any elements. 041 @SuppressWarnings("unchecked") 042 public static <K, V> ImmutableBiMap<K, V> of() { 043 return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY; 044 } 045 046 /** Returns an immutable bimap containing a single entry. */ 047 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) { 048 checkEntryNotNull(k1, v1); 049 return new RegularImmutableBiMap<>(new Object[] {k1, v1}, 1); 050 } 051 052 /** 053 * Returns an immutable map containing the given entries, in order. 054 * 055 * @throws IllegalArgumentException if duplicate keys or values are added 056 */ 057 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) { 058 checkEntryNotNull(k1, v1); 059 checkEntryNotNull(k2, v2); 060 return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2}, 2); 061 } 062 063 /** 064 * Returns an immutable map containing the given entries, in order. 065 * 066 * @throws IllegalArgumentException if duplicate keys or values are added 067 */ 068 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { 069 checkEntryNotNull(k1, v1); 070 checkEntryNotNull(k2, v2); 071 checkEntryNotNull(k3, v3); 072 return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2, k3, v3}, 3); 073 } 074 075 /** 076 * Returns an immutable map containing the given entries, in order. 077 * 078 * @throws IllegalArgumentException if duplicate keys or values are added 079 */ 080 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 081 checkEntryNotNull(k1, v1); 082 checkEntryNotNull(k2, v2); 083 checkEntryNotNull(k3, v3); 084 checkEntryNotNull(k4, v4); 085 return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2, k3, v3, k4, v4}, 4); 086 } 087 088 /** 089 * Returns an immutable map containing the given entries, in order. 090 * 091 * @throws IllegalArgumentException if duplicate keys or values are added 092 */ 093 public static <K, V> ImmutableBiMap<K, V> of( 094 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 095 checkEntryNotNull(k1, v1); 096 checkEntryNotNull(k2, v2); 097 checkEntryNotNull(k3, v3); 098 checkEntryNotNull(k4, v4); 099 checkEntryNotNull(k5, v5); 100 return new RegularImmutableBiMap<K, V>( 101 new Object[] {k1, v1, k2, v2, k3, v3, k4, v4, k5, v5}, 5); 102 } 103 104 // looking for of() with > 5 entries? Use the builder instead. 105 106 /** 107 * Returns a new builder. The generated builder is equivalent to the builder created by the {@link 108 * Builder} constructor. 109 */ 110 public static <K, V> Builder<K, V> builder() { 111 return new Builder<>(); 112 } 113 114 /** 115 * Returns a new builder, expecting the specified number of entries to be added. 116 * 117 * <p>If {@code expectedSize} is exactly the number of entries added to the builder before {@link 118 * Builder#build} is called, the builder is likely to perform better than an unsized {@link 119 * #builder()} would have. 120 * 121 * <p>It is not specified if any performance benefits apply if {@code expectedSize} is close to, 122 * but not exactly, the number of entries added to the builder. 123 * 124 * @since 23.1 125 */ 126 @Beta 127 public static <K, V> Builder<K, V> builderWithExpectedSize(int expectedSize) { 128 checkNonnegative(expectedSize, "expectedSize"); 129 return new Builder<>(expectedSize); 130 } 131 132 /** 133 * A builder for creating immutable bimap instances, especially {@code public static final} bimaps 134 * ("constant bimaps"). Example: 135 * 136 * <pre>{@code 137 * static final ImmutableBiMap<String, Integer> WORD_TO_INT = 138 * new ImmutableBiMap.Builder<String, Integer>() 139 * .put("one", 1) 140 * .put("two", 2) 141 * .put("three", 3) 142 * .build(); 143 * }</pre> 144 * 145 * <p>For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods are even more 146 * convenient. 147 * 148 * <p>By default, a {@code Builder} will generate bimaps that iterate over entries in the order 149 * they were inserted into the builder. For example, in the above example, {@code 150 * WORD_TO_INT.entrySet()} is guaranteed to iterate over the entries in the order {@code "one"=1, 151 * "two"=2, "three"=3}, and {@code keySet()} and {@code values()} respect the same order. If you 152 * want a different order, consider using {@link #orderEntriesByValue(Comparator)}, which changes 153 * this builder to sort entries by value. 154 * 155 * <p>Builder instances can be reused - it is safe to call {@link #build} multiple times to build 156 * multiple bimaps in series. Each bimap is a superset of the bimaps created before it. 157 * 158 * @since 2.0 159 */ 160 public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> { 161 /** 162 * Creates a new builder. The returned builder is equivalent to the builder generated by {@link 163 * ImmutableBiMap#builder}. 164 */ 165 public Builder() { 166 super(); 167 } 168 169 Builder(int size) { 170 super(size); 171 } 172 173 /** 174 * Associates {@code key} with {@code value} in the built bimap. Duplicate keys or values are 175 * not allowed, and will cause {@link #build} to fail. 176 */ 177 @CanIgnoreReturnValue 178 @Override 179 public Builder<K, V> put(K key, V value) { 180 super.put(key, value); 181 return this; 182 } 183 184 /** 185 * Adds the given {@code entry} to the bimap. Duplicate keys or values are not allowed, and will 186 * cause {@link #build} to fail. 187 * 188 * @since 19.0 189 */ 190 @CanIgnoreReturnValue 191 @Override 192 public Builder<K, V> put(Entry<? extends K, ? extends V> entry) { 193 super.put(entry); 194 return this; 195 } 196 197 /** 198 * Associates all of the given map's keys and values in the built bimap. Duplicate keys or 199 * values are not allowed, and will cause {@link #build} to fail. 200 * 201 * @throws NullPointerException if any key or value in {@code map} is null 202 */ 203 @CanIgnoreReturnValue 204 @Override 205 public Builder<K, V> putAll(Map<? extends K, ? extends V> map) { 206 super.putAll(map); 207 return this; 208 } 209 210 /** 211 * Adds all of the given entries to the built bimap. Duplicate keys or values are not allowed, 212 * and will cause {@link #build} to fail. 213 * 214 * @throws NullPointerException if any key, value, or entry is null 215 * @since 19.0 216 */ 217 @CanIgnoreReturnValue 218 @Beta 219 @Override 220 public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) { 221 super.putAll(entries); 222 return this; 223 } 224 225 /** 226 * Configures this {@code Builder} to order entries by value according to the specified 227 * comparator. 228 * 229 * <p>The sort order is stable, that is, if two entries have values that compare as equivalent, 230 * the entry that was inserted first will be first in the built map's iteration order. 231 * 232 * @throws IllegalStateException if this method was already called 233 * @since 19.0 234 */ 235 @CanIgnoreReturnValue 236 @Beta 237 @Override 238 public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) { 239 super.orderEntriesByValue(valueComparator); 240 return this; 241 } 242 243 /** 244 * Returns a newly-created immutable bimap. The iteration order of the returned bimap is the 245 * order in which entries were inserted into the builder, unless {@link #orderEntriesByValue} 246 * was called, in which case entries are sorted by value. 247 * 248 * @throws IllegalArgumentException if duplicate keys or values were added 249 */ 250 @Override 251 public ImmutableBiMap<K, V> build() { 252 if (size == 0) { 253 return of(); 254 } 255 sortEntries(); 256 entriesUsed = true; 257 return new RegularImmutableBiMap<K, V>(alternatingKeysAndValues, size); 258 } 259 } 260 261 /** 262 * Returns an immutable bimap containing the same entries as {@code map}. If {@code map} somehow 263 * contains entries with duplicate keys (for example, if it is a {@code SortedMap} whose 264 * comparator is not <i>consistent with equals</i>), the results of this method are undefined. 265 * 266 * <p>The returned {@code BiMap} iterates over entries in the same order as the {@code entrySet} 267 * of the original map. 268 * 269 * <p>Despite the method name, this method attempts to avoid actually copying the data when it is 270 * safe to do so. The exact circumstances under which a copy will or will not be performed are 271 * undocumented and subject to change. 272 * 273 * @throws IllegalArgumentException if two keys have the same value or two values have the same 274 * key 275 * @throws NullPointerException if any key or value in {@code map} is null 276 */ 277 public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) { 278 if (map instanceof ImmutableBiMap) { 279 @SuppressWarnings("unchecked") // safe since map is not writable 280 ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map; 281 // TODO(lowasser): if we need to make a copy of a BiMap because the 282 // forward map is a view, don't make a copy of the non-view delegate map 283 if (!bimap.isPartialView()) { 284 return bimap; 285 } 286 } 287 return copyOf(map.entrySet()); 288 } 289 290 /** 291 * Returns an immutable bimap containing the given entries. The returned bimap iterates over 292 * entries in the same order as the original iterable. 293 * 294 * @throws IllegalArgumentException if two keys have the same value or two values have the same 295 * key 296 * @throws NullPointerException if any key, value, or entry is null 297 * @since 19.0 298 */ 299 @Beta 300 public static <K, V> ImmutableBiMap<K, V> copyOf( 301 Iterable<? extends Entry<? extends K, ? extends V>> entries) { 302 int estimatedSize = 303 (entries instanceof Collection) 304 ? ((Collection<?>) entries).size() 305 : ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY; 306 return new Builder<K, V>(estimatedSize).putAll(entries).build(); 307 } 308 309 ImmutableBiMap() {} 310 311 /** 312 * {@inheritDoc} 313 * 314 * <p>The inverse of an {@code ImmutableBiMap} is another {@code ImmutableBiMap}. 315 */ 316 @Override 317 public abstract ImmutableBiMap<V, K> inverse(); 318 319 /** 320 * Returns an immutable set of the values in this map, in the same order they appear in {@link 321 * #entrySet}. 322 */ 323 @Override 324 public ImmutableSet<V> values() { 325 return inverse().keySet(); 326 } 327 328 @Override 329 final ImmutableSet<V> createValues() { 330 throw new AssertionError("should never be called"); 331 } 332 333 /** 334 * Guaranteed to throw an exception and leave the bimap unmodified. 335 * 336 * @throws UnsupportedOperationException always 337 * @deprecated Unsupported operation. 338 */ 339 @CanIgnoreReturnValue 340 @Deprecated 341 @Override 342 public V forcePut(K key, V value) { 343 throw new UnsupportedOperationException(); 344 } 345 346 /** 347 * Serialized type for all ImmutableBiMap instances. It captures the logical contents and they are 348 * reconstructed using public factory methods. This ensures that the implementation types remain 349 * as implementation details. 350 * 351 * <p>Since the bimap is immutable, ImmutableBiMap doesn't require special logic for keeping the 352 * bimap and its inverse in sync during serialization, the way AbstractBiMap does. 353 */ 354 private static class SerializedForm extends ImmutableMap.SerializedForm { 355 SerializedForm(ImmutableBiMap<?, ?> bimap) { 356 super(bimap); 357 } 358 359 @Override 360 Object readResolve() { 361 Builder<Object, Object> builder = new Builder<>(); 362 return createMap(builder); 363 } 364 365 private static final long serialVersionUID = 0; 366 } 367 368 @Override 369 Object writeReplace() { 370 return new SerializedForm(this); 371 } 372}