Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2008 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.collect;
     18 
     19 import com.google.common.annotations.GwtCompatible;
     20 
     21 import java.util.Map;
     22 
     23 /**
     24  * An immutable {@link BiMap} with reliable user-specified iteration order. Does
     25  * not permit null keys or values. An {@code ImmutableBiMap} and its inverse
     26  * have the same iteration ordering.
     27  *
     28  * <p>An instance of {@code ImmutableBiMap} contains its own data and will
     29  * <i>never</i> change. {@code ImmutableBiMap} is convenient for
     30  * {@code public static final} maps ("constant maps") and also lets you easily
     31  * make a "defensive copy" of a bimap provided to your class by a caller.
     32  *
     33  * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
     34  * it has no public or protected constructors. Thus, instances of this class are
     35  * guaranteed to be immutable.
     36  *
     37  * @author Jared Levy
     38  * @since 2.0 (imported from Google Collections Library)
     39  */
     40 @GwtCompatible(serializable = true, emulated = true)
     41 public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V>
     42     implements BiMap<K, V> {
     43 
     44   /**
     45    * Returns the empty bimap.
     46    */
     47   // Casting to any type is safe because the set will never hold any elements.
     48   @SuppressWarnings("unchecked")
     49   public static <K, V> ImmutableBiMap<K, V> of() {
     50     return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;
     51   }
     52 
     53   /**
     54    * Returns an immutable bimap containing a single entry.
     55    */
     56   public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
     57     return new SingletonImmutableBiMap<K, V>(k1, v1);
     58   }
     59 
     60   /**
     61    * Returns an immutable map containing the given entries, in order.
     62    *
     63    * @throws IllegalArgumentException if duplicate keys or values are added
     64    */
     65   public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
     66     return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
     67   }
     68 
     69   /**
     70    * Returns an immutable map containing the given entries, in order.
     71    *
     72    * @throws IllegalArgumentException if duplicate keys or values are added
     73    */
     74   public static <K, V> ImmutableBiMap<K, V> of(
     75       K k1, V v1, K k2, V v2, K k3, V v3) {
     76     return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
     77   }
     78 
     79   /**
     80    * Returns an immutable map containing the given entries, in order.
     81    *
     82    * @throws IllegalArgumentException if duplicate keys or values are added
     83    */
     84   public static <K, V> ImmutableBiMap<K, V> of(
     85       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
     86     return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3),
     87         entryOf(k4, v4));
     88   }
     89 
     90   /**
     91    * Returns an immutable map containing the given entries, in order.
     92    *
     93    * @throws IllegalArgumentException if duplicate keys or values are added
     94    */
     95   public static <K, V> ImmutableBiMap<K, V> of(
     96       K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
     97     return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3),
     98         entryOf(k4, v4), entryOf(k5, v5));
     99   }
    100 
    101   // looking for of() with > 5 entries? Use the builder instead.
    102 
    103   /**
    104    * Returns a new builder. The generated builder is equivalent to the builder
    105    * created by the {@link Builder} constructor.
    106    */
    107   public static <K, V> Builder<K, V> builder() {
    108     return new Builder<K, V>();
    109   }
    110 
    111   /**
    112    * A builder for creating immutable bimap instances, especially {@code public
    113    * static final} bimaps ("constant bimaps"). Example: <pre>   {@code
    114    *
    115    *   static final ImmutableBiMap<String, Integer> WORD_TO_INT =
    116    *       new ImmutableBiMap.Builder<String, Integer>()
    117    *           .put("one", 1)
    118    *           .put("two", 2)
    119    *           .put("three", 3)
    120    *           .build();}</pre>
    121    *
    122    * <p>For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods
    123    * are even more convenient.
    124    *
    125    * <p>Builder instances can be reused - it is safe to call {@link #build}
    126    * multiple times to build multiple bimaps in series. Each bimap is a superset
    127    * of the bimaps created before it.
    128    *
    129    * @since 2.0 (imported from Google Collections Library)
    130    */
    131   public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
    132 
    133     /**
    134      * Creates a new builder. The returned builder is equivalent to the builder
    135      * generated by {@link ImmutableBiMap#builder}.
    136      */
    137     public Builder() {}
    138 
    139     /**
    140      * Associates {@code key} with {@code value} in the built bimap. Duplicate
    141      * keys or values are not allowed, and will cause {@link #build} to fail.
    142      */
    143     @Override public Builder<K, V> put(K key, V value) {
    144       super.put(key, value);
    145       return this;
    146     }
    147 
    148     /**
    149      * Associates all of the given map's keys and values in the built bimap.
    150      * Duplicate keys or values are not allowed, and will cause {@link #build}
    151      * to fail.
    152      *
    153      * @throws NullPointerException if any key or value in {@code map} is null
    154      */
    155     @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
    156       super.putAll(map);
    157       return this;
    158     }
    159 
    160     /**
    161      * Returns a newly-created immutable bimap.
    162      *
    163      * @throws IllegalArgumentException if duplicate keys or values were added
    164      */
    165     @Override public ImmutableBiMap<K, V> build() {
    166       switch (size) {
    167         case 0:
    168           return of();
    169         case 1:
    170           return of(entries[0].getKey(), entries[0].getValue());
    171         default:
    172           return new RegularImmutableBiMap<K, V>(size, entries);
    173       }
    174     }
    175   }
    176 
    177   /**
    178    * Returns an immutable bimap containing the same entries as {@code map}. If
    179    * {@code map} somehow contains entries with duplicate keys (for example, if
    180    * it is a {@code SortedMap} whose comparator is not <i>consistent with
    181    * equals</i>), the results of this method are undefined.
    182    *
    183    * <p>Despite the method name, this method attempts to avoid actually copying
    184    * the data when it is safe to do so. The exact circumstances under which a
    185    * copy will or will not be performed are undocumented and subject to change.
    186    *
    187    * @throws IllegalArgumentException if two keys have the same value
    188    * @throws NullPointerException if any key or value in {@code map} is null
    189    */
    190   public static <K, V> ImmutableBiMap<K, V> copyOf(
    191       Map<? extends K, ? extends V> map) {
    192     if (map instanceof ImmutableBiMap) {
    193       @SuppressWarnings("unchecked") // safe since map is not writable
    194       ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
    195       // TODO(user): if we need to make a copy of a BiMap because the
    196       // forward map is a view, don't make a copy of the non-view delegate map
    197       if (!bimap.isPartialView()) {
    198         return bimap;
    199       }
    200     }
    201     Entry<?, ?>[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
    202     switch (entries.length) {
    203       case 0:
    204         return of();
    205       case 1:
    206         @SuppressWarnings("unchecked") // safe covariant cast in this context
    207         Entry<K, V> entry = (Entry<K, V>) entries[0];
    208         return of(entry.getKey(), entry.getValue());
    209       default:
    210         return new RegularImmutableBiMap<K, V>(entries);
    211     }
    212   }
    213 
    214   private static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
    215 
    216   ImmutableBiMap() {}
    217 
    218   /**
    219    * {@inheritDoc}
    220    *
    221    * <p>The inverse of an {@code ImmutableBiMap} is another
    222    * {@code ImmutableBiMap}.
    223    */
    224   @Override
    225   public abstract ImmutableBiMap<V, K> inverse();
    226 
    227   /**
    228    * Returns an immutable set of the values in this map. The values are in the
    229    * same order as the parameters used to build this map.
    230    */
    231   @Override public ImmutableSet<V> values() {
    232     return inverse().keySet();
    233   }
    234 
    235   /**
    236    * Guaranteed to throw an exception and leave the bimap unmodified.
    237    *
    238    * @throws UnsupportedOperationException always
    239    * @deprecated Unsupported operation.
    240    */
    241   @Deprecated
    242   @Override
    243   public V forcePut(K key, V value) {
    244     throw new UnsupportedOperationException();
    245   }
    246 
    247   /**
    248    * Serialized type for all ImmutableBiMap instances. It captures the logical
    249    * contents and they are reconstructed using public factory methods. This
    250    * ensures that the implementation types remain as implementation details.
    251    *
    252    * Since the bimap is immutable, ImmutableBiMap doesn't require special logic
    253    * for keeping the bimap and its inverse in sync during serialization, the way
    254    * AbstractBiMap does.
    255    */
    256   private static class SerializedForm extends ImmutableMap.SerializedForm {
    257     SerializedForm(ImmutableBiMap<?, ?> bimap) {
    258       super(bimap);
    259     }
    260     @Override Object readResolve() {
    261       Builder<Object, Object> builder = new Builder<Object, Object>();
    262       return createMap(builder);
    263     }
    264     private static final long serialVersionUID = 0;
    265   }
    266 
    267   @Override Object writeReplace() {
    268     return new SerializedForm(this);
    269   }
    270 }
    271