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 com.google.common.annotations.Beta;
020import com.google.common.annotations.GwtCompatible;
021import com.google.errorprone.annotations.CanIgnoreReturnValue;
022import java.util.Arrays;
023import java.util.Comparator;
024import java.util.Map;
025import java.util.function.Function;
026import java.util.stream.Collector;
027import java.util.stream.Collectors;
028
029/**
030 * A {@link BiMap} whose contents will never change, with many other important properties detailed
031 * at {@link ImmutableCollection}.
032 *
033 * @author Jared Levy
034 * @since 2.0
035 */
036@GwtCompatible(serializable = true, emulated = true)
037public abstract class ImmutableBiMap<K, V> extends ImmutableBiMapFauxverideShim<K, V>
038    implements BiMap<K, V> {
039
040  /**
041   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableBiMap} whose
042   * keys and values are the result of applying the provided mapping functions to the input
043   * elements. Entries appear in the result {@code ImmutableBiMap} in encounter order.
044   *
045   * <p>If the mapped keys or values contain duplicates
046   * (according to {@link Object#equals(Object)}, an {@code IllegalArgumentException} is thrown
047   * when the collection operation is performed. (This differs from the {@code Collector} returned
048   * by {@link Collectors#toMap(Function, Function)}, which throws an
049   * {@code IllegalStateException}.)
050   *
051   * @since 21.0
052   */
053  @Beta
054  public static <T, K, V> Collector<T, ?, ImmutableBiMap<K, V>> toImmutableBiMap(
055      Function<? super T, ? extends K> keyFunction,
056      Function<? super T, ? extends V> valueFunction) {
057    return CollectCollectors.toImmutableBiMap(keyFunction, valueFunction);
058  }
059
060  /**
061   * Returns the empty bimap.
062   */
063  // Casting to any type is safe because the set will never hold any elements.
064  @SuppressWarnings("unchecked")
065  public static <K, V> ImmutableBiMap<K, V> of() {
066    return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY;
067  }
068
069  /**
070   * Returns an immutable bimap containing a single entry.
071   */
072  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
073    return new SingletonImmutableBiMap<K, V>(k1, v1);
074  }
075
076  /**
077   * Returns an immutable map containing the given entries, in order.
078   *
079   * @throws IllegalArgumentException if duplicate keys or values are added
080   */
081  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
082    return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2));
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, K k3, V v3) {
091    return RegularImmutableBiMap.fromEntries(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
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, K k4, V v4) {
100    return RegularImmutableBiMap.fromEntries(
101        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
102  }
103
104  /**
105   * Returns an immutable map containing the given entries, in order.
106   *
107   * @throws IllegalArgumentException if duplicate keys or values are added
108   */
109  public static <K, V> ImmutableBiMap<K, V> of(
110      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
111    return RegularImmutableBiMap.fromEntries(
112        entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
113  }
114
115  // looking for of() with > 5 entries? Use the builder instead.
116
117  /**
118   * Returns a new builder. The generated builder is equivalent to the builder
119   * created by the {@link Builder} constructor.
120   */
121  public static <K, V> Builder<K, V> builder() {
122    return new Builder<K, V>();
123  }
124
125  /**
126   * A builder for creating immutable bimap instances, especially {@code public
127   * static final} bimaps ("constant bimaps"). Example: <pre>   {@code
128   *
129   *   static final ImmutableBiMap<String, Integer> WORD_TO_INT =
130   *       new ImmutableBiMap.Builder<String, Integer>()
131   *           .put("one", 1)
132   *           .put("two", 2)
133   *           .put("three", 3)
134   *           .build();}</pre>
135   *
136   * <p>For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods
137   * are even more convenient.
138   *
139   * <p>By default, a {@code Builder} will generate bimaps that iterate over entries in the order
140   * they were inserted into the builder.  For example, in the above example,
141   * {@code WORD_TO_INT.entrySet()} is guaranteed to iterate over the entries in the order
142   * {@code "one"=1, "two"=2, "three"=3}, and {@code keySet()} and {@code values()} respect the same
143   * order. If you want a different order, consider using
144   * {@link #orderEntriesByValue(Comparator)}, which changes this builder to sort
145   * entries by value.
146   *
147   * <p>Builder instances can be reused - it is safe to call {@link #build}
148   * multiple times to build multiple bimaps in series. Each bimap is a superset
149   * of the bimaps created before it.
150   *
151   * @since 2.0
152   */
153  public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
154
155    /**
156     * Creates a new builder. The returned builder is equivalent to the builder
157     * generated by {@link ImmutableBiMap#builder}.
158     */
159    public Builder() {}
160
161    Builder(int size) {
162      super(size);
163    }
164
165    /**
166     * Associates {@code key} with {@code value} in the built bimap. Duplicate
167     * keys or values are not allowed, and will cause {@link #build} to fail.
168     */
169    @CanIgnoreReturnValue
170    @Override
171    public Builder<K, V> put(K key, V value) {
172      super.put(key, value);
173      return this;
174    }
175
176    /**
177     * Adds the given {@code entry} to the bimap.  Duplicate keys or values
178     * are not allowed, and will cause {@link #build} to fail.
179     *
180     * @since 19.0
181     */
182    @CanIgnoreReturnValue
183    @Override
184    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
185      super.put(entry);
186      return this;
187    }
188
189    /**
190     * Associates all of the given map's keys and values in the built bimap.
191     * Duplicate keys or values are not allowed, and will cause {@link #build}
192     * to fail.
193     *
194     * @throws NullPointerException if any key or value in {@code map} is null
195     */
196    @CanIgnoreReturnValue
197    @Override
198    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
199      super.putAll(map);
200      return this;
201    }
202
203    /**
204     * Adds all of the given entries to the built bimap.  Duplicate keys or
205     * values are not allowed, and will cause {@link #build} to fail.
206     *
207     * @throws NullPointerException if any key, value, or entry is null
208     * @since 19.0
209     */
210    @CanIgnoreReturnValue
211    @Beta
212    @Override
213    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
214      super.putAll(entries);
215      return this;
216    }
217
218    /**
219     * Configures this {@code Builder} to order entries by value according to the specified
220     * comparator.
221     *
222     * <p>The sort order is stable, that is, if two entries have values that compare
223     * as equivalent, the entry that was inserted first will be first in the built map's
224     * iteration order.
225     *
226     * @throws IllegalStateException if this method was already called
227     * @since 19.0
228     */
229    @CanIgnoreReturnValue
230    @Beta
231    @Override
232    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
233      super.orderEntriesByValue(valueComparator);
234      return this;
235    }
236
237    @Override
238    @CanIgnoreReturnValue
239    Builder<K, V> combine(ImmutableMap.Builder<K, V> builder) {
240      super.combine(builder);
241      return this;
242    }
243
244    /**
245     * Returns a newly-created immutable bimap.  The iteration order of the returned bimap is
246     * the order in which entries were inserted into the builder, unless
247     * {@link #orderEntriesByValue} was called, in which case entries are sorted by value.
248     *
249     * @throws IllegalArgumentException if duplicate keys or values were added
250     */
251    @Override
252    public ImmutableBiMap<K, V> build() {
253      switch (size) {
254        case 0:
255          return of();
256        case 1:
257          return of(entries[0].getKey(), entries[0].getValue());
258        default:
259          /*
260           * If entries is full, then this implementation may end up using the entries array
261           * directly and writing over the entry objects with non-terminal entries, but this is
262           * safe; if this Builder is used further, it will grow the entries array (so it can't
263           * affect the original array), and future build() calls will always copy any entry
264           * objects that cannot be safely reused.
265           */
266          if (valueComparator != null) {
267            if (entriesUsed) {
268              entries = Arrays.copyOf(entries, size);
269            }
270            Arrays.sort(
271                entries,
272                0,
273                size,
274                Ordering.from(valueComparator).onResultOf(Maps.<V>valueFunction()));
275          }
276          entriesUsed = size == entries.length;
277          return RegularImmutableBiMap.fromEntryArray(size, entries);
278      }
279    }
280  }
281
282  /**
283   * Returns an immutable bimap containing the same entries as {@code map}. If
284   * {@code map} somehow contains entries with duplicate keys (for example, if
285   * it is a {@code SortedMap} whose comparator is not <i>consistent with
286   * equals</i>), the results of this method are undefined.
287   *
288   * <p>The returned {@code BiMap} iterates over entries in the same order as the
289   * {@code entrySet} of the original map.
290   *
291   * <p>Despite the method name, this method attempts to avoid actually copying
292   * the data when it is safe to do so. The exact circumstances under which a
293   * copy will or will not be performed are undocumented and subject to change.
294   *
295   * @throws IllegalArgumentException if two keys have the same value or two values have the same
296   *     key
297   * @throws NullPointerException if any key or value in {@code map} is null
298   */
299  public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
300    if (map instanceof ImmutableBiMap) {
301      @SuppressWarnings("unchecked") // safe since map is not writable
302      ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
303      // TODO(lowasser): if we need to make a copy of a BiMap because the
304      // forward map is a view, don't make a copy of the non-view delegate map
305      if (!bimap.isPartialView()) {
306        return bimap;
307      }
308    }
309    return copyOf(map.entrySet());
310  }
311
312  /**
313   * Returns an immutable bimap containing the given entries.  The returned bimap iterates over
314   * entries in the same order as the original iterable.
315   *
316   * @throws IllegalArgumentException if two keys have the same value or two
317   *         values have the same key
318   * @throws NullPointerException if any key, value, or entry is null
319   * @since 19.0
320   */
321  @Beta
322  public static <K, V> ImmutableBiMap<K, V> copyOf(
323      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
324    @SuppressWarnings("unchecked") // we'll only be using getKey and getValue, which are covariant
325    Entry<K, V>[] entryArray = (Entry<K, V>[]) Iterables.toArray(entries, EMPTY_ENTRY_ARRAY);
326    switch (entryArray.length) {
327      case 0:
328        return of();
329      case 1:
330        Entry<K, V> entry = entryArray[0];
331        return of(entry.getKey(), entry.getValue());
332      default:
333        /*
334         * The current implementation will end up using entryArray directly, though it will write
335         * over the (arbitrary, potentially mutable) Entry objects actually stored in entryArray.
336         */
337        return RegularImmutableBiMap.fromEntries(entryArray);
338    }
339  }
340
341  ImmutableBiMap() {}
342
343  /**
344   * {@inheritDoc}
345   *
346   * <p>The inverse of an {@code ImmutableBiMap} is another
347   * {@code ImmutableBiMap}.
348   */
349  @Override
350  public abstract ImmutableBiMap<V, K> inverse();
351
352  /**
353   * Returns an immutable set of the values in this map, in the same order they appear in {@link
354   * #entrySet}.
355   */
356  @Override
357  public ImmutableSet<V> values() {
358    return inverse().keySet();
359  }
360
361  @Override
362  final ImmutableSet<V> createValues() {
363    throw new AssertionError("should never be called");
364  }
365
366  /**
367   * Guaranteed to throw an exception and leave the bimap unmodified.
368   *
369   * @throws UnsupportedOperationException always
370   * @deprecated Unsupported operation.
371   */
372  @CanIgnoreReturnValue
373  @Deprecated
374  @Override
375  public V forcePut(K key, V value) {
376    throw new UnsupportedOperationException();
377  }
378
379  /**
380   * Serialized type for all ImmutableBiMap instances. It captures the logical
381   * contents and they are reconstructed using public factory methods. This
382   * ensures that the implementation types remain as implementation details.
383   *
384   * Since the bimap is immutable, ImmutableBiMap doesn't require special logic
385   * for keeping the bimap and its inverse in sync during serialization, the way
386   * AbstractBiMap does.
387   */
388  private static class SerializedForm extends ImmutableMap.SerializedForm {
389    SerializedForm(ImmutableBiMap<?, ?> bimap) {
390      super(bimap);
391    }
392
393    @Override
394    Object readResolve() {
395      Builder<Object, Object> builder = new Builder<Object, Object>();
396      return createMap(builder);
397    }
398
399    private static final long serialVersionUID = 0;
400  }
401
402  @Override
403  Object writeReplace() {
404    return new SerializedForm(this);
405  }
406}