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.GwtIncompatible; 026import com.google.common.annotations.J2ktIncompatible; 027import com.google.common.annotations.VisibleForTesting; 028import com.google.errorprone.annotations.CanIgnoreReturnValue; 029import com.google.errorprone.annotations.DoNotCall; 030import java.io.InvalidObjectException; 031import java.io.ObjectInputStream; 032import java.util.Arrays; 033import java.util.Comparator; 034import java.util.Map; 035import java.util.function.BinaryOperator; 036import java.util.function.Function; 037import java.util.stream.Collector; 038import java.util.stream.Collectors; 039import org.jspecify.annotations.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) 049public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> { 050 051 /** 052 * Returns a {@link Collector} that accumulates elements into an {@code ImmutableBiMap} whose keys 053 * and values are the result of applying the provided mapping functions to the input elements. 054 * Entries appear in the result {@code ImmutableBiMap} in encounter order. 055 * 056 * <p>If the mapped keys or values contain duplicates (according to {@link 057 * Object#equals(Object)}), an {@code IllegalArgumentException} is thrown when the collection 058 * operation is performed. (This differs from the {@code Collector} returned by {@link 059 * Collectors#toMap(Function, Function)}, which throws an {@code IllegalStateException}.) 060 * 061 * @since 21.0 062 */ 063 public static <T extends @Nullable Object, K, V> 064 Collector<T, ?, ImmutableBiMap<K, V>> toImmutableBiMap( 065 Function<? super T, ? extends K> keyFunction, 066 Function<? super T, ? extends V> valueFunction) { 067 return CollectCollectors.toImmutableBiMap(keyFunction, valueFunction); 068 } 069 070 /** 071 * Returns the empty bimap. 072 * 073 * <p><b>Performance note:</b> the instance returned is a singleton. 074 */ 075 // Casting to any type is safe because the set will never hold any elements. 076 @SuppressWarnings("unchecked") 077 public static <K, V> ImmutableBiMap<K, V> of() { 078 return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY; 079 } 080 081 /** Returns an immutable bimap containing a single entry. */ 082 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) { 083 return new SingletonImmutableBiMap<>(k1, v1); 084 } 085 086 /** 087 * Returns an immutable map containing the given entries, in order. 088 * 089 * @throws IllegalArgumentException if duplicate keys or values are added 090 */ 091 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) { 092 return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2)); 093 } 094 095 /** 096 * Returns an immutable map containing the given entries, in order. 097 * 098 * @throws IllegalArgumentException if duplicate keys or values are added 099 */ 100 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { 101 return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3)); 102 } 103 104 /** 105 * Returns an immutable map containing the given entries, in order. 106 * 107 * @throws IllegalArgumentException if duplicate keys or values are added 108 */ 109 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 110 return RegularImmutableBiMap.fromEntries( 111 entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4)); 112 } 113 114 /** 115 * Returns an immutable map containing the given entries, in order. 116 * 117 * @throws IllegalArgumentException if duplicate keys or values are added 118 */ 119 public static <K, V> ImmutableBiMap<K, V> of( 120 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 121 return RegularImmutableBiMap.fromEntries( 122 entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5)); 123 } 124 125 /** 126 * Returns an immutable map containing the given entries, in order. 127 * 128 * @throws IllegalArgumentException if duplicate keys or values are added 129 * @since 31.0 130 */ 131 public static <K, V> ImmutableBiMap<K, V> of( 132 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) { 133 return RegularImmutableBiMap.fromEntries( 134 entryOf(k1, v1), 135 entryOf(k2, v2), 136 entryOf(k3, v3), 137 entryOf(k4, v4), 138 entryOf(k5, v5), 139 entryOf(k6, v6)); 140 } 141 142 /** 143 * Returns an immutable map containing the given entries, in order. 144 * 145 * @throws IllegalArgumentException if duplicate keys or values are added 146 * @since 31.0 147 */ 148 public static <K, V> ImmutableBiMap<K, V> of( 149 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) { 150 return RegularImmutableBiMap.fromEntries( 151 entryOf(k1, v1), 152 entryOf(k2, v2), 153 entryOf(k3, v3), 154 entryOf(k4, v4), 155 entryOf(k5, v5), 156 entryOf(k6, v6), 157 entryOf(k7, v7)); 158 } 159 160 /** 161 * Returns an immutable map containing the given entries, in order. 162 * 163 * @throws IllegalArgumentException if duplicate keys or values are added 164 * @since 31.0 165 */ 166 public static <K, V> ImmutableBiMap<K, V> of( 167 K k1, 168 V v1, 169 K k2, 170 V v2, 171 K k3, 172 V v3, 173 K k4, 174 V v4, 175 K k5, 176 V v5, 177 K k6, 178 V v6, 179 K k7, 180 V v7, 181 K k8, 182 V v8) { 183 return RegularImmutableBiMap.fromEntries( 184 entryOf(k1, v1), 185 entryOf(k2, v2), 186 entryOf(k3, v3), 187 entryOf(k4, v4), 188 entryOf(k5, v5), 189 entryOf(k6, v6), 190 entryOf(k7, v7), 191 entryOf(k8, v8)); 192 } 193 194 /** 195 * Returns an immutable map containing the given entries, in order. 196 * 197 * @throws IllegalArgumentException if duplicate keys or values are added 198 * @since 31.0 199 */ 200 public static <K, V> ImmutableBiMap<K, V> of( 201 K k1, 202 V v1, 203 K k2, 204 V v2, 205 K k3, 206 V v3, 207 K k4, 208 V v4, 209 K k5, 210 V v5, 211 K k6, 212 V v6, 213 K k7, 214 V v7, 215 K k8, 216 V v8, 217 K k9, 218 V v9) { 219 return RegularImmutableBiMap.fromEntries( 220 entryOf(k1, v1), 221 entryOf(k2, v2), 222 entryOf(k3, v3), 223 entryOf(k4, v4), 224 entryOf(k5, v5), 225 entryOf(k6, v6), 226 entryOf(k7, v7), 227 entryOf(k8, v8), 228 entryOf(k9, v9)); 229 } 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 public final @Nullable V forcePut(K key, V value) { 610 throw new UnsupportedOperationException(); 611 } 612 613 /** 614 * Serialized type for all ImmutableBiMap instances. It captures the logical contents and they are 615 * reconstructed using public factory methods. This ensures that the implementation types remain 616 * as implementation details. 617 * 618 * <p>Since the bimap is immutable, ImmutableBiMap doesn't require special logic for keeping the 619 * bimap and its inverse in sync during serialization, the way AbstractBiMap does. 620 */ 621 @J2ktIncompatible // serialization 622 private static class SerializedForm<K, V> extends ImmutableMap.SerializedForm<K, V> { 623 SerializedForm(ImmutableBiMap<K, V> bimap) { 624 super(bimap); 625 } 626 627 @Override 628 Builder<K, V> makeBuilder(int size) { 629 return new Builder<>(size); 630 } 631 632 @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0; 633 } 634 635 @Override 636 @J2ktIncompatible // serialization 637 Object writeReplace() { 638 return new SerializedForm<>(this); 639 } 640 641 @J2ktIncompatible // serialization 642 private void readObject(ObjectInputStream stream) throws InvalidObjectException { 643 throw new InvalidObjectException("Use SerializedForm"); 644 } 645 646 /** 647 * Not supported. Use {@link #toImmutableBiMap} instead. This method exists only to hide {@link 648 * ImmutableMap#toImmutableMap(Function, Function)} from consumers of {@code ImmutableBiMap}. 649 * 650 * @throws UnsupportedOperationException always 651 * @deprecated Use {@link ImmutableBiMap#toImmutableBiMap(Function, Function)}. 652 */ 653 @Deprecated 654 @DoNotCall("Use toImmutableBiMap") 655 public static <T extends @Nullable Object, K, V> 656 Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( 657 Function<? super T, ? extends K> keyFunction, 658 Function<? super T, ? extends V> valueFunction) { 659 throw new UnsupportedOperationException(); 660 } 661 662 /** 663 * Not supported. This method does not make sense for {@code BiMap}. This method exists only to 664 * hide {@link ImmutableMap#toImmutableMap(Function, Function, BinaryOperator)} from consumers of 665 * {@code ImmutableBiMap}. 666 * 667 * @throws UnsupportedOperationException always 668 * @deprecated Merging values does not make sense for a {@code BiMap}. 669 */ 670 @Deprecated 671 @DoNotCall("Use toImmutableBiMap") 672 public static <T extends @Nullable Object, K, V> 673 Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( 674 Function<? super T, ? extends K> keyFunction, 675 Function<? super T, ? extends V> valueFunction, 676 BinaryOperator<V> mergeFunction) { 677 throw new UnsupportedOperationException(); 678 } 679 680 @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0xcafebabe; 681}