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