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.checkState; 020import static com.google.common.collect.CollectPreconditions.checkNonnegative; 021import static java.util.Arrays.sort; 022import static java.util.Objects.requireNonNull; 023 024import com.google.common.annotations.GwtCompatible; 025import com.google.common.annotations.J2ktIncompatible; 026import com.google.common.annotations.VisibleForTesting; 027import com.google.errorprone.annotations.CanIgnoreReturnValue; 028import com.google.errorprone.annotations.DoNotCall; 029import java.io.InvalidObjectException; 030import java.io.ObjectInputStream; 031import java.util.Arrays; 032import java.util.Comparator; 033import java.util.Map; 034import java.util.function.BinaryOperator; 035import java.util.function.Function; 036import java.util.stream.Collector; 037import java.util.stream.Collectors; 038import javax.annotation.CheckForNull; 039import org.checkerframework.checker.nullness.qual.Nullable; 040 041/** 042 * A {@link BiMap} whose contents will never change, with many other important properties detailed 043 * at {@link ImmutableCollection}. 044 * 045 * @author Jared Levy 046 * @since 2.0 047 */ 048@GwtCompatible(serializable = true, emulated = true) 049@ElementTypesAreNonnullByDefault 050public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> { 051 052 /** 053 * Returns a {@link Collector} that accumulates elements into an {@code ImmutableBiMap} whose keys 054 * and values are the result of applying the provided mapping functions to the input elements. 055 * Entries appear in the result {@code ImmutableBiMap} in encounter order. 056 * 057 * <p>If the mapped keys or values contain duplicates (according to {@link 058 * Object#equals(Object)}), an {@code IllegalArgumentException} is thrown when the collection 059 * operation is performed. (This differs from the {@code Collector} returned by {@link 060 * Collectors#toMap(Function, Function)}, which throws an {@code IllegalStateException}.) 061 * 062 * @since 21.0 063 */ 064 public static <T extends @Nullable Object, K, V> 065 Collector<T, ?, ImmutableBiMap<K, V>> toImmutableBiMap( 066 Function<? super T, ? extends K> keyFunction, 067 Function<? super T, ? extends V> valueFunction) { 068 return CollectCollectors.toImmutableBiMap(keyFunction, valueFunction); 069 } 070 071 /** 072 * Returns the empty bimap. 073 * 074 * <p><b>Performance note:</b> the instance returned is a singleton. 075 */ 076 // Casting to any type is safe because the set will never hold any elements. 077 @SuppressWarnings("unchecked") 078 public static <K, V> ImmutableBiMap<K, V> of() { 079 return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY; 080 } 081 082 /** Returns an immutable bimap containing a single entry. */ 083 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) { 084 return new SingletonImmutableBiMap<>(k1, v1); 085 } 086 087 /** 088 * Returns an immutable map containing the given entries, in order. 089 * 090 * @throws IllegalArgumentException if duplicate keys or values are added 091 */ 092 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) { 093 return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2)); 094 } 095 096 /** 097 * Returns an immutable map containing the given entries, in order. 098 * 099 * @throws IllegalArgumentException if duplicate keys or values are added 100 */ 101 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { 102 return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3)); 103 } 104 105 /** 106 * Returns an immutable map containing the given entries, in order. 107 * 108 * @throws IllegalArgumentException if duplicate keys or values are added 109 */ 110 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 111 return RegularImmutableBiMap.fromEntries( 112 entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4)); 113 } 114 115 /** 116 * Returns an immutable map containing the given entries, in order. 117 * 118 * @throws IllegalArgumentException if duplicate keys or values are added 119 */ 120 public static <K, V> ImmutableBiMap<K, V> of( 121 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 122 return RegularImmutableBiMap.fromEntries( 123 entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5)); 124 } 125 126 /** 127 * Returns an immutable map containing the given entries, in order. 128 * 129 * @throws IllegalArgumentException if duplicate keys or values are added 130 * @since 31.0 131 */ 132 public static <K, V> ImmutableBiMap<K, V> of( 133 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { 134 return RegularImmutableBiMap.fromEntries( 135 entryOf(k1, v1), 136 entryOf(k2, v2), 137 entryOf(k3, v3), 138 entryOf(k4, v4), 139 entryOf(k5, v5), 140 entryOf(k6, v6)); 141 } 142 143 /** 144 * Returns an immutable map containing the given entries, in order. 145 * 146 * @throws IllegalArgumentException if duplicate keys or values are added 147 * @since 31.0 148 */ 149 public static <K, V> ImmutableBiMap<K, V> of( 150 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) { 151 return RegularImmutableBiMap.fromEntries( 152 entryOf(k1, v1), 153 entryOf(k2, v2), 154 entryOf(k3, v3), 155 entryOf(k4, v4), 156 entryOf(k5, v5), 157 entryOf(k6, v6), 158 entryOf(k7, v7)); 159 } 160 161 /** 162 * Returns an immutable map containing the given entries, in order. 163 * 164 * @throws IllegalArgumentException if duplicate keys or values are added 165 * @since 31.0 166 */ 167 public static <K, V> ImmutableBiMap<K, V> of( 168 K k1, 169 V v1, 170 K k2, 171 V v2, 172 K k3, 173 V v3, 174 K k4, 175 V v4, 176 K k5, 177 V v5, 178 K k6, 179 V v6, 180 K k7, 181 V v7, 182 K k8, 183 V v8) { 184 return RegularImmutableBiMap.fromEntries( 185 entryOf(k1, v1), 186 entryOf(k2, v2), 187 entryOf(k3, v3), 188 entryOf(k4, v4), 189 entryOf(k5, v5), 190 entryOf(k6, v6), 191 entryOf(k7, v7), 192 entryOf(k8, v8)); 193 } 194 195 /** 196 * Returns an immutable map containing the given entries, in order. 197 * 198 * @throws IllegalArgumentException if duplicate keys or values are added 199 * @since 31.0 200 */ 201 public static <K, V> ImmutableBiMap<K, V> of( 202 K k1, 203 V v1, 204 K k2, 205 V v2, 206 K k3, 207 V v3, 208 K k4, 209 V v4, 210 K k5, 211 V v5, 212 K k6, 213 V v6, 214 K k7, 215 V v7, 216 K k8, 217 V v8, 218 K k9, 219 V v9) { 220 return RegularImmutableBiMap.fromEntries( 221 entryOf(k1, v1), 222 entryOf(k2, v2), 223 entryOf(k3, v3), 224 entryOf(k4, v4), 225 entryOf(k5, v5), 226 entryOf(k6, v6), 227 entryOf(k7, v7), 228 entryOf(k8, v8), 229 entryOf(k9, v9)); 230 } 231 /** 232 * Returns an immutable map containing the given entries, in order. 233 * 234 * @throws IllegalArgumentException if duplicate keys or values are added 235 * @since 31.0 236 */ 237 public static <K, V> ImmutableBiMap<K, V> of( 238 K k1, 239 V v1, 240 K k2, 241 V v2, 242 K k3, 243 V v3, 244 K k4, 245 V v4, 246 K k5, 247 V v5, 248 K k6, 249 V v6, 250 K k7, 251 V v7, 252 K k8, 253 V v8, 254 K k9, 255 V v9, 256 K k10, 257 V v10) { 258 return RegularImmutableBiMap.fromEntries( 259 entryOf(k1, v1), 260 entryOf(k2, v2), 261 entryOf(k3, v3), 262 entryOf(k4, v4), 263 entryOf(k5, v5), 264 entryOf(k6, v6), 265 entryOf(k7, v7), 266 entryOf(k8, v8), 267 entryOf(k9, v9), 268 entryOf(k10, v10)); 269 } 270 271 // looking for of() with > 10 entries? Use the builder or ofEntries instead. 272 273 /** 274 * Returns an immutable map containing the given entries, in order. 275 * 276 * @throws IllegalArgumentException if duplicate keys or values are provided 277 * @since 31.0 278 */ 279 @SafeVarargs 280 public static <K, V> ImmutableBiMap<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { 281 @SuppressWarnings("unchecked") // we will only ever read these 282 Entry<K, V>[] entries2 = (Entry<K, V>[]) entries; 283 return RegularImmutableBiMap.fromEntries(entries2); 284 } 285 286 /** 287 * Returns a new builder. The generated builder is equivalent to the builder created by the {@link 288 * Builder} constructor. 289 */ 290 public static <K, V> Builder<K, V> builder() { 291 return new Builder<>(); 292 } 293 294 /** 295 * Returns a new builder, expecting the specified number of entries to be added. 296 * 297 * <p>If {@code expectedSize} is exactly the number of entries added to the builder before {@link 298 * Builder#build} is called, the builder is likely to perform better than an unsized {@link 299 * #builder()} would have. 300 * 301 * <p>It is not specified if any performance benefits apply if {@code expectedSize} is close to, 302 * but not exactly, the number of entries added to the builder. 303 * 304 * @since 23.1 305 */ 306 public static <K, V> Builder<K, V> builderWithExpectedSize(int expectedSize) { 307 checkNonnegative(expectedSize, "expectedSize"); 308 return new Builder<>(expectedSize); 309 } 310 311 /** 312 * A builder for creating immutable bimap instances, especially {@code public static final} bimaps 313 * ("constant bimaps"). Example: 314 * 315 * <pre>{@code 316 * static final ImmutableBiMap<String, Integer> WORD_TO_INT = 317 * new ImmutableBiMap.Builder<String, Integer>() 318 * .put("one", 1) 319 * .put("two", 2) 320 * .put("three", 3) 321 * .buildOrThrow(); 322 * }</pre> 323 * 324 * <p>For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods are even more 325 * convenient. 326 * 327 * <p>By default, a {@code Builder} will generate bimaps that iterate over entries in the order 328 * they were inserted into the builder. For example, in the above example, {@code 329 * WORD_TO_INT.entrySet()} is guaranteed to iterate over the entries in the order {@code "one"=1, 330 * "two"=2, "three"=3}, and {@code keySet()} and {@code values()} respect the same order. If you 331 * want a different order, consider using {@link #orderEntriesByValue(Comparator)}, which changes 332 * this builder to sort entries by value. 333 * 334 * <p>Builder instances can be reused - it is safe to call {@link #buildOrThrow} multiple times to 335 * build multiple bimaps in series. Each bimap is a superset of the bimaps created before it. 336 * 337 * @since 2.0 338 */ 339 public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> { 340 341 /** 342 * Creates a new builder. The returned builder is equivalent to the builder generated by {@link 343 * ImmutableBiMap#builder}. 344 */ 345 public Builder() {} 346 347 Builder(int size) { 348 super(size); 349 } 350 351 /** 352 * Associates {@code key} with {@code value} in the built bimap. Duplicate keys or values are 353 * not allowed, and will cause {@link #build} to fail. 354 */ 355 @CanIgnoreReturnValue 356 @Override 357 public Builder<K, V> put(K key, V value) { 358 super.put(key, value); 359 return this; 360 } 361 362 /** 363 * Adds the given {@code entry} to the bimap. Duplicate keys or values are not allowed, and will 364 * cause {@link #build} to fail. 365 * 366 * @since 19.0 367 */ 368 @CanIgnoreReturnValue 369 @Override 370 public Builder<K, V> put(Entry<? extends K, ? extends V> entry) { 371 super.put(entry); 372 return this; 373 } 374 375 /** 376 * Associates all of the given map's keys and values in the built bimap. Duplicate keys or 377 * values are not allowed, and will cause {@link #build} to fail. 378 * 379 * @throws NullPointerException if any key or value in {@code map} is null 380 */ 381 @CanIgnoreReturnValue 382 @Override 383 public Builder<K, V> putAll(Map<? extends K, ? extends V> map) { 384 super.putAll(map); 385 return this; 386 } 387 388 /** 389 * Adds all of the given entries to the built bimap. Duplicate keys or values are not allowed, 390 * and will cause {@link #build} to fail. 391 * 392 * @throws NullPointerException if any key, value, or entry is null 393 * @since 19.0 394 */ 395 @CanIgnoreReturnValue 396 @Override 397 public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) { 398 super.putAll(entries); 399 return this; 400 } 401 402 /** 403 * Configures this {@code Builder} to order entries by value according to the specified 404 * comparator. 405 * 406 * <p>The sort order is stable, that is, if two entries have values that compare as equivalent, 407 * the entry that was inserted first will be first in the built map's iteration order. 408 * 409 * @throws IllegalStateException if this method was already called 410 * @since 19.0 411 */ 412 @CanIgnoreReturnValue 413 @Override 414 public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) { 415 super.orderEntriesByValue(valueComparator); 416 return this; 417 } 418 419 @Override 420 @CanIgnoreReturnValue 421 Builder<K, V> combine(ImmutableMap.Builder<K, V> builder) { 422 super.combine(builder); 423 return this; 424 } 425 426 /** 427 * Returns a newly-created immutable bimap. The iteration order of the returned bimap is the 428 * order in which entries were inserted into the builder, unless {@link #orderEntriesByValue} 429 * was called, in which case entries are sorted by value. 430 * 431 * <p>Prefer the equivalent method {@link #buildOrThrow()} to make it explicit that the method 432 * will throw an exception if there are duplicate keys or values. The {@code build()} method 433 * will soon be deprecated. 434 * 435 * @throws IllegalArgumentException if duplicate keys or values were added 436 */ 437 @Override 438 public ImmutableBiMap<K, V> build() { 439 return buildOrThrow(); 440 } 441 442 /** 443 * Returns a newly-created immutable bimap, or throws an exception if any key or value was added 444 * more than once. The iteration order of the returned bimap is the order in which entries were 445 * inserted into the builder, unless {@link #orderEntriesByValue} was called, in which case 446 * entries are sorted by value. 447 * 448 * @throws IllegalArgumentException if duplicate keys or values were added 449 * @since 31.0 450 */ 451 @Override 452 public ImmutableBiMap<K, V> buildOrThrow() { 453 switch (size) { 454 case 0: 455 return of(); 456 case 1: 457 // requireNonNull is safe because the first `size` elements have been filled in. 458 Entry<K, V> onlyEntry = requireNonNull(entries[0]); 459 return of(onlyEntry.getKey(), onlyEntry.getValue()); 460 default: 461 /* 462 * If entries is full, or if hash flooding is detected, then this implementation may end 463 * up using the entries array directly and writing over the entry objects with 464 * non-terminal entries, but this is safe; if this Builder is used further, it will grow 465 * the entries array (so it can't affect the original array), and future build() calls 466 * will always copy any entry objects that cannot be safely reused. 467 */ 468 if (valueComparator != null) { 469 if (entriesUsed) { 470 entries = Arrays.copyOf(entries, size); 471 } 472 sort( 473 (Entry<K, V>[]) entries, // Entries up to size are not null 474 0, 475 size, 476 Ordering.from(valueComparator).onResultOf(Maps.valueFunction())); 477 } 478 entriesUsed = true; 479 return RegularImmutableBiMap.fromEntryArray(size, entries); 480 } 481 } 482 483 /** 484 * Throws {@link UnsupportedOperationException}. This method is inherited from {@link 485 * ImmutableMap.Builder}, but it does not make sense for bimaps. 486 * 487 * @throws UnsupportedOperationException always 488 * @deprecated This method does not make sense for bimaps and should not be called. 489 * @since 31.1 490 */ 491 @DoNotCall 492 @Deprecated 493 @Override 494 public ImmutableBiMap<K, V> buildKeepingLast() { 495 throw new UnsupportedOperationException("Not supported for bimaps"); 496 } 497 498 @Override 499 @VisibleForTesting 500 ImmutableBiMap<K, V> buildJdkBacked() { 501 checkState( 502 valueComparator == null, 503 "buildJdkBacked is for tests only, doesn't support orderEntriesByValue"); 504 switch (size) { 505 case 0: 506 return of(); 507 case 1: 508 // requireNonNull is safe because the first `size` elements have been filled in. 509 Entry<K, V> onlyEntry = requireNonNull(entries[0]); 510 return of(onlyEntry.getKey(), onlyEntry.getValue()); 511 default: 512 entriesUsed = true; 513 return RegularImmutableBiMap.fromEntryArray(size, entries); 514 } 515 } 516 } 517 518 /** 519 * Returns an immutable bimap containing the same entries as {@code map}. If {@code map} somehow 520 * contains entries with duplicate keys (for example, if it is a {@code SortedMap} whose 521 * comparator is not <i>consistent with equals</i>), the results of this method are undefined. 522 * 523 * <p>The returned {@code BiMap} iterates over entries in the same order as the {@code entrySet} 524 * of the original map. 525 * 526 * <p>Despite the method name, this method attempts to avoid actually copying the data when it is 527 * safe to do so. The exact circumstances under which a copy will or will not be performed are 528 * undocumented and subject to change. 529 * 530 * @throws IllegalArgumentException if two keys have the same value or two values have the same 531 * key 532 * @throws NullPointerException if any key or value in {@code map} is null 533 */ 534 public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) { 535 if (map instanceof ImmutableBiMap) { 536 @SuppressWarnings("unchecked") // safe since map is not writable 537 ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map; 538 // TODO(lowasser): if we need to make a copy of a BiMap because the 539 // forward map is a view, don't make a copy of the non-view delegate map 540 if (!bimap.isPartialView()) { 541 return bimap; 542 } 543 } 544 return copyOf(map.entrySet()); 545 } 546 547 /** 548 * Returns an immutable bimap containing the given entries. The returned bimap iterates over 549 * entries in the same order as the original iterable. 550 * 551 * @throws IllegalArgumentException if two keys have the same value or two values have the same 552 * key 553 * @throws NullPointerException if any key, value, or entry is null 554 * @since 19.0 555 */ 556 public static <K, V> ImmutableBiMap<K, V> copyOf( 557 Iterable<? extends Entry<? extends K, ? extends V>> entries) { 558 @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant 559 Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY); 560 switch (entryArray.length) { 561 case 0: 562 return of(); 563 case 1: 564 Entry<K, V> entry = entryArray[0]; 565 return of(entry.getKey(), entry.getValue()); 566 default: 567 /* 568 * The current implementation will end up using entryArray directly, though it will write 569 * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray. 570 */ 571 return RegularImmutableBiMap.fromEntries(entryArray); 572 } 573 } 574 575 ImmutableBiMap() {} 576 577 /** 578 * {@inheritDoc} 579 * 580 * <p>The inverse of an {@code ImmutableBiMap} is another {@code ImmutableBiMap}. 581 */ 582 @Override 583 public abstract ImmutableBiMap<V, K> inverse(); 584 585 /** 586 * Returns an immutable set of the values in this map, in the same order they appear in {@link 587 * #entrySet}. 588 */ 589 @Override 590 public ImmutableSet<V> values() { 591 return inverse().keySet(); 592 } 593 594 @Override 595 final ImmutableSet<V> createValues() { 596 throw new AssertionError("should never be called"); 597 } 598 599 /** 600 * Guaranteed to throw an exception and leave the bimap unmodified. 601 * 602 * @throws UnsupportedOperationException always 603 * @deprecated Unsupported operation. 604 */ 605 @CanIgnoreReturnValue 606 @Deprecated 607 @Override 608 @DoNotCall("Always throws UnsupportedOperationException") 609 @CheckForNull 610 public final V forcePut(K key, V value) { 611 throw new UnsupportedOperationException(); 612 } 613 614 /** 615 * Serialized type for all ImmutableBiMap instances. It captures the logical contents and they are 616 * reconstructed using public factory methods. This ensures that the implementation types remain 617 * as implementation details. 618 * 619 * <p>Since the bimap is immutable, ImmutableBiMap doesn't require special logic for keeping the 620 * bimap and its inverse in sync during serialization, the way AbstractBiMap does. 621 */ 622 @J2ktIncompatible // serialization 623 private static class SerializedForm<K, V> extends ImmutableMap.SerializedForm<K, V> { 624 SerializedForm(ImmutableBiMap<K, V> bimap) { 625 super(bimap); 626 } 627 628 @Override 629 Builder<K, V> makeBuilder(int size) { 630 return new Builder<>(size); 631 } 632 633 private static final long serialVersionUID = 0; 634 } 635 636 @Override 637 @J2ktIncompatible // serialization 638 Object writeReplace() { 639 return new SerializedForm<>(this); 640 } 641 642 @J2ktIncompatible // serialization 643 private void readObject(ObjectInputStream stream) throws InvalidObjectException { 644 throw new InvalidObjectException("Use SerializedForm"); 645 } 646 647 /** 648 * Not supported. Use {@link #toImmutableBiMap} instead. This method exists only to hide {@link 649 * ImmutableMap#toImmutableMap(Function, Function)} from consumers of {@code ImmutableBiMap}. 650 * 651 * @throws UnsupportedOperationException always 652 * @deprecated Use {@link ImmutableBiMap#toImmutableBiMap}. 653 */ 654 @Deprecated 655 @DoNotCall("Use toImmutableBiMap") 656 public static <T extends @Nullable Object, K, V> 657 Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( 658 Function<? super T, ? extends K> keyFunction, 659 Function<? super T, ? extends V> valueFunction) { 660 throw new UnsupportedOperationException(); 661 } 662 663 /** 664 * Not supported. This method does not make sense for {@code BiMap}. This method exists only to 665 * hide {@link ImmutableMap#toImmutableMap(Function, Function, BinaryOperator)} from consumers of 666 * {@code ImmutableBiMap}. 667 * 668 * @throws UnsupportedOperationException always 669 * @deprecated 670 */ 671 @Deprecated 672 @DoNotCall("Use toImmutableBiMap") 673 public static <T extends @Nullable Object, K, V> 674 Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( 675 Function<? super T, ? extends K> keyFunction, 676 Function<? super T, ? extends V> valueFunction, 677 BinaryOperator<V> mergeFunction) { 678 throw new UnsupportedOperationException(); 679 } 680 681 private static final long serialVersionUID = 0xcafebabe; 682}