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