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