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@SuppressWarnings("TooManyParameters")
049@GwtCompatible
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  /**
233   * Returns an immutable map containing the given entries, in order.
234   *
235   * @throws IllegalArgumentException if duplicate keys or values are added
236   * @since 31.0
237   */
238  public static <K, V> ImmutableBiMap<K, V> of(
239      K k1,
240      V v1,
241      K k2,
242      V v2,
243      K k3,
244      V v3,
245      K k4,
246      V v4,
247      K k5,
248      V v5,
249      K k6,
250      V v6,
251      K k7,
252      V v7,
253      K k8,
254      V v8,
255      K k9,
256      V v9,
257      K k10,
258      V v10) {
259    return RegularImmutableBiMap.fromEntries(
260        entryOf(k1, v1),
261        entryOf(k2, v2),
262        entryOf(k3, v3),
263        entryOf(k4, v4),
264        entryOf(k5, v5),
265        entryOf(k6, v6),
266        entryOf(k7, v7),
267        entryOf(k8, v8),
268        entryOf(k9, v9),
269        entryOf(k10, v10));
270  }
271
272  // looking for of() with > 10 entries? Use the builder or ofEntries instead.
273
274  /**
275   * Returns an immutable map containing the given entries, in order.
276   *
277   * @throws IllegalArgumentException if duplicate keys or values are provided
278   * @since 31.0
279   */
280  @SafeVarargs
281  public static <K, V> ImmutableBiMap<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
282    @SuppressWarnings("unchecked") // we will only ever read these
283    Entry<K, V>[] entries2 = (Entry<K, V>[]) entries;
284    return RegularImmutableBiMap.fromEntries(entries2);
285  }
286
287  /**
288   * Returns a new builder. The generated builder is equivalent to the builder created by the {@link
289   * Builder} constructor.
290   */
291  public static <K, V> Builder<K, V> builder() {
292    return new Builder<>();
293  }
294
295  /**
296   * Returns a new builder, expecting the specified number of entries to be added.
297   *
298   * <p>If {@code expectedSize} is exactly the number of entries added to the builder before {@link
299   * Builder#build()} is called, the builder is likely to perform better than an unsized {@link
300   * #builder()} would have.
301   *
302   * <p>It is not specified if any performance benefits apply if {@code expectedSize} is close to,
303   * but not exactly, the number of entries added to the builder.
304   *
305   * @since 23.1
306   */
307  public static <K, V> Builder<K, V> builderWithExpectedSize(int expectedSize) {
308    checkNonnegative(expectedSize, "expectedSize");
309    return new Builder<>(expectedSize);
310  }
311
312  /**
313   * A builder for creating immutable bimap instances, especially {@code public static final} bimaps
314   * ("constant bimaps"). Example:
315   *
316   * {@snippet :
317   * static final ImmutableBiMap<String, Integer> WORD_TO_INT =
318   *     new ImmutableBiMap.Builder<String, Integer>()
319   *         .put("one", 1)
320   *         .put("two", 2)
321   *         .put("three", 3)
322   *         .buildOrThrow();
323   * }
324   *
325   * <p>For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods are even more
326   * convenient.
327   *
328   * <p>By default, a {@code Builder} will generate bimaps that iterate over entries in the order
329   * they were inserted into the builder. For example, in the above example, {@code
330   * WORD_TO_INT.entrySet()} is guaranteed to iterate over the entries in the order {@code "one"=1,
331   * "two"=2, "three"=3}, and {@code keySet()} and {@code values()} respect the same order. If you
332   * want a different order, consider using {@link #orderEntriesByValue(Comparator)}, which changes
333   * this builder to sort entries by value.
334   *
335   * <p>Builder instances can be reused - it is safe to call {@link #buildOrThrow} multiple times to
336   * build multiple bimaps in series. Each bimap is a superset of the bimaps created before it.
337   *
338   * @since 2.0
339   */
340  public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
341
342    /**
343     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
344     * ImmutableBiMap#builder}.
345     */
346    public Builder() {}
347
348    Builder(int size) {
349      super(size);
350    }
351
352    /**
353     * Associates {@code key} with {@code value} in the built bimap. Duplicate keys or values are
354     * not allowed, and will cause {@link #build()} to fail.
355     */
356    @CanIgnoreReturnValue
357    @Override
358    public Builder<K, V> put(K key, V value) {
359      super.put(key, value);
360      return this;
361    }
362
363    /**
364     * Adds the given {@code entry} to the bimap. Duplicate keys or values are not allowed, and will
365     * cause {@link #build()} to fail.
366     *
367     * @since 19.0
368     */
369    @CanIgnoreReturnValue
370    @Override
371    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
372      super.put(entry);
373      return this;
374    }
375
376    /**
377     * Associates all of the given map's keys and values in the built bimap. Duplicate keys or
378     * values are not allowed, and will cause {@link #build()} to fail.
379     *
380     * @throws NullPointerException if any key or value in {@code map} is null
381     */
382    @CanIgnoreReturnValue
383    @Override
384    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
385      super.putAll(map);
386      return this;
387    }
388
389    /**
390     * Adds all of the given entries to the built bimap. Duplicate keys or values are not allowed,
391     * and will cause {@link #build()} to fail.
392     *
393     * @throws NullPointerException if any key, value, or entry is null
394     * @since 19.0
395     */
396    @CanIgnoreReturnValue
397    @Override
398    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
399      super.putAll(entries);
400      return this;
401    }
402
403    /**
404     * Configures this {@code Builder} to order entries by value according to the specified
405     * comparator.
406     *
407     * <p>The sort order is stable, that is, if two entries have values that compare as equivalent,
408     * the entry that was inserted first will be first in the built map's iteration order.
409     *
410     * @throws IllegalStateException if this method was already called
411     * @since 19.0
412     */
413    @CanIgnoreReturnValue
414    @Override
415    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
416      super.orderEntriesByValue(valueComparator);
417      return this;
418    }
419
420    @Override
421    @CanIgnoreReturnValue
422    Builder<K, V> combine(ImmutableMap.Builder<K, V> builder) {
423      super.combine(builder);
424      return this;
425    }
426
427    /**
428     * Returns a newly-created immutable bimap. The iteration order of the returned bimap is the
429     * order in which entries were inserted into the builder, unless {@link #orderEntriesByValue}
430     * was called, in which case entries are sorted by value.
431     *
432     * <p>Prefer the equivalent method {@link #buildOrThrow()} to make it explicit that the method
433     * will throw an exception if there are duplicate keys or values. The {@code build()} method
434     * will soon be deprecated.
435     *
436     * @throws IllegalArgumentException if duplicate keys or values were added
437     */
438    @Override
439    public ImmutableBiMap<K, V> build() {
440      return buildOrThrow();
441    }
442
443    /**
444     * Returns a newly-created immutable bimap, or throws an exception if any key or value was added
445     * more than once. The iteration order of the returned bimap is the order in which entries were
446     * inserted into the builder, unless {@link #orderEntriesByValue} was called, in which case
447     * entries are sorted by value.
448     *
449     * @throws IllegalArgumentException if duplicate keys or values were added
450     * @since 31.0
451     */
452    @Override
453    public ImmutableBiMap<K, V> buildOrThrow() {
454      switch (size) {
455        case 0:
456          return of();
457        case 1:
458          // requireNonNull is safe because the first `size` elements have been filled in.
459          Entry<K, V> onlyEntry = requireNonNull(entries[0]);
460          return of(onlyEntry.getKey(), onlyEntry.getValue());
461        default:
462          /*
463           * If entries is full, or if hash flooding is detected, then this implementation may end
464           * up using the entries array directly and writing over the entry objects with
465           * non-terminal entries, but this is safe; if this Builder is used further, it will grow
466           * the entries array (so it can't affect the original array), and future build() calls
467           * will always copy any entry objects that cannot be safely reused.
468           */
469          if (valueComparator != null) {
470            if (entriesUsed) {
471              entries = Arrays.copyOf(entries, size);
472            }
473            sort(
474                entries, // Entries up to size are not null
475                0,
476                size,
477                Ordering.from(valueComparator).onResultOf(Entry::getValue));
478          }
479          entriesUsed = true;
480          return RegularImmutableBiMap.fromEntryArray(size, entries);
481      }
482    }
483
484    /**
485     * Throws {@link UnsupportedOperationException}. This method is inherited from {@link
486     * ImmutableMap.Builder}, but it does not make sense for bimaps.
487     *
488     * @throws UnsupportedOperationException always
489     * @deprecated This method does not make sense for bimaps and should not be called.
490     * @since 31.1
491     */
492    @DoNotCall
493    @Deprecated
494    @Override
495    public ImmutableBiMap<K, V> buildKeepingLast() {
496      throw new UnsupportedOperationException("Not supported for bimaps");
497    }
498
499    @Override
500    @VisibleForTesting
501    ImmutableBiMap<K, V> buildJdkBacked() {
502      checkState(
503          valueComparator == null,
504          "buildJdkBacked is for tests only, doesn't support orderEntriesByValue");
505      switch (size) {
506        case 0:
507          return of();
508        case 1:
509          // requireNonNull is safe because the first `size` elements have been filled in.
510          Entry<K, V> onlyEntry = requireNonNull(entries[0]);
511          return of(onlyEntry.getKey(), onlyEntry.getValue());
512        default:
513          entriesUsed = true;
514          return RegularImmutableBiMap.fromEntryArray(size, entries);
515      }
516    }
517  }
518
519  /**
520   * Returns an immutable bimap containing the same entries as {@code map}. If {@code map} somehow
521   * contains entries with duplicate keys (for example, if it is a {@code SortedMap} whose
522   * comparator is not <i>consistent with equals</i>), the results of this method are undefined.
523   *
524   * <p>The returned {@code BiMap} iterates over entries in the same order as the {@code entrySet}
525   * of the original map.
526   *
527   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
528   * safe to do so. The exact circumstances under which a copy will or will not be performed are
529   * undocumented and subject to change.
530   *
531   * @throws IllegalArgumentException if two keys have the same value or two values have the same
532   *     key
533   * @throws NullPointerException if any key or value in {@code map} is null
534   */
535  public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
536    if (map instanceof ImmutableBiMap) {
537      @SuppressWarnings("unchecked") // safe since map is not writable
538      ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
539      // TODO(lowasser): if we need to make a copy of a BiMap because the
540      // forward map is a view, don't make a copy of the non-view delegate map
541      if (!bimap.isPartialView()) {
542        return bimap;
543      }
544    }
545    return copyOf(map.entrySet());
546  }
547
548  /**
549   * Returns an immutable bimap containing the given entries. The returned bimap iterates over
550   * entries in the same order as the original iterable.
551   *
552   * @throws IllegalArgumentException if two keys have the same value or two values have the same
553   *     key
554   * @throws NullPointerException if any key, value, or entry is null
555   * @since 19.0
556   */
557  public static <K, V> ImmutableBiMap<K, V> copyOf(
558      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
559    @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant
560    Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
561    switch (entryArray.length) {
562      case 0:
563        return of();
564      case 1:
565        Entry<K, V> entry = entryArray[0];
566        return of(entry.getKey(), entry.getValue());
567      default:
568        /*
569         * The current implementation will end up using entryArray directly, though it will write
570         * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray.
571         */
572        return RegularImmutableBiMap.fromEntries(entryArray);
573    }
574  }
575
576  ImmutableBiMap() {}
577
578  /**
579   * {@inheritDoc}
580   *
581   * <p>The inverse of an {@code ImmutableBiMap} is another {@code ImmutableBiMap}.
582   */
583  @Override
584  public abstract ImmutableBiMap<V, K> inverse();
585
586  /**
587   * Returns an immutable set of the values in this map, in the same order they appear in {@link
588   * #entrySet()}.
589   */
590  @Override
591  public final ImmutableSet<V> values() {
592    return inverse().keySet();
593  }
594
595  /**
596   * Guaranteed to throw an exception and leave the bimap unmodified.
597   *
598   * @throws UnsupportedOperationException always
599   * @deprecated Unsupported operation.
600   */
601  @CanIgnoreReturnValue
602  @Deprecated
603  @Override
604  @DoNotCall("Always throws UnsupportedOperationException")
605  public final @Nullable V forcePut(K key, V value) {
606    throw new UnsupportedOperationException();
607  }
608
609  /**
610   * Serialized type for all ImmutableBiMap instances. It captures the logical contents and they are
611   * reconstructed using public factory methods. This ensures that the implementation types remain
612   * as implementation details.
613   *
614   * <p>Since the bimap is immutable, ImmutableBiMap doesn't require special logic for keeping the
615   * bimap and its inverse in sync during serialization, the way AbstractBiMap does.
616   */
617  @J2ktIncompatible // serialization
618  private static final class SerializedForm<K, V> extends ImmutableMap.SerializedForm<K, V> {
619    SerializedForm(ImmutableBiMap<K, V> bimap) {
620      super(bimap);
621    }
622
623    @Override
624    Builder<K, V> makeBuilder(int size) {
625      return new Builder<>(size);
626    }
627
628    @GwtIncompatible private static final long serialVersionUID = 0;
629  }
630
631  @Override
632  @J2ktIncompatible // serialization
633  Object writeReplace() {
634    return new SerializedForm<>(this);
635  }
636
637  @J2ktIncompatible // serialization
638  private void readObject(ObjectInputStream stream) throws InvalidObjectException {
639    throw new InvalidObjectException("Use SerializedForm");
640  }
641
642  /**
643   * Not supported. Use {@link #toImmutableBiMap} instead. This method exists only to hide {@link
644   * ImmutableMap#toImmutableMap(Function, Function)} from consumers of {@code ImmutableBiMap}.
645   *
646   * @throws UnsupportedOperationException always
647   * @deprecated Use {@link ImmutableBiMap#toImmutableBiMap(Function, Function)}.
648   */
649  @Deprecated
650  @DoNotCall("Use toImmutableBiMap")
651  public static <T extends @Nullable Object, K, V>
652      Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
653          Function<? super T, ? extends K> keyFunction,
654          Function<? super T, ? extends V> valueFunction) {
655    throw new UnsupportedOperationException();
656  }
657
658  /**
659   * Not supported. This method does not make sense for {@code BiMap}. This method exists only to
660   * hide {@link ImmutableMap#toImmutableMap(Function, Function, BinaryOperator)} from consumers of
661   * {@code ImmutableBiMap}.
662   *
663   * @throws UnsupportedOperationException always
664   * @deprecated Merging values does not make sense for a {@code BiMap}.
665   */
666  @Deprecated
667  @DoNotCall("Use toImmutableBiMap")
668  public static <T extends @Nullable Object, K, V>
669      Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
670          Function<? super T, ? extends K> keyFunction,
671          Function<? super T, ? extends V> valueFunction,
672          BinaryOperator<V> mergeFunction) {
673    throw new UnsupportedOperationException();
674  }
675
676  @GwtIncompatible @J2ktIncompatible   private static final long serialVersionUID = 0xcafebabe;
677}