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