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 017 package com.google.common.collect; 018 019 import com.google.common.annotations.GwtCompatible; 020 021 import java.util.Map; 022 023 import javax.annotation.Nullable; 024 025 /** 026 * An immutable {@link BiMap} with reliable user-specified iteration order. Does 027 * not permit null keys or values. An {@code ImmutableBiMap} and its inverse 028 * have the same iteration ordering. 029 * 030 * <p>An instance of {@code ImmutableBiMap} contains its own data and will 031 * <i>never</i> change. {@code ImmutableBiMap} is convenient for 032 * {@code public static final} maps ("constant maps") and also lets you easily 033 * make a "defensive copy" of a bimap provided to your class by a caller. 034 * 035 * <p><b>Note</b>: Although this class is not final, it cannot be subclassed as 036 * it has no public or protected constructors. Thus, instances of this class are 037 * guaranteed to be immutable. 038 * 039 * @author Jared Levy 040 * @since 2 (imported from Google Collections Library) 041 */ 042 @GwtCompatible(serializable = true, emulated = true) 043 public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> 044 implements BiMap<K, V> { 045 046 private static final ImmutableBiMap<Object, Object> EMPTY_IMMUTABLE_BIMAP 047 = new EmptyBiMap(); 048 049 /** 050 * Returns the empty bimap. 051 */ 052 // Casting to any type is safe because the set will never hold any elements. 053 @SuppressWarnings("unchecked") 054 public static <K, V> ImmutableBiMap<K, V> of() { 055 return (ImmutableBiMap<K, V>) EMPTY_IMMUTABLE_BIMAP; 056 } 057 058 /** 059 * Returns an immutable bimap containing a single entry. 060 */ 061 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) { 062 return new RegularImmutableBiMap<K, V>(ImmutableMap.of(k1, v1)); 063 } 064 065 /** 066 * Returns an immutable map containing the given entries, in order. 067 * 068 * @throws IllegalArgumentException if duplicate keys or values are added 069 */ 070 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) { 071 return new RegularImmutableBiMap<K, V>(ImmutableMap.of(k1, v1, k2, v2)); 072 } 073 074 /** 075 * Returns an immutable map containing the given entries, in order. 076 * 077 * @throws IllegalArgumentException if duplicate keys or values are added 078 */ 079 public static <K, V> ImmutableBiMap<K, V> of( 080 K k1, V v1, K k2, V v2, K k3, V v3) { 081 return new RegularImmutableBiMap<K, V>(ImmutableMap.of( 082 k1, v1, k2, v2, k3, v3)); 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( 091 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 092 return new RegularImmutableBiMap<K, V>(ImmutableMap.of( 093 k1, v1, k2, v2, k3, v3, k4, v4)); 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( 102 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 103 return new RegularImmutableBiMap<K, V>(ImmutableMap.of( 104 k1, v1, k2, v2, k3, v3, k4, v4, k5, v5)); 105 } 106 107 // looking for of() with > 5 entries? Use the builder instead. 108 109 /** 110 * Returns a new builder. The generated builder is equivalent to the builder 111 * created by the {@link Builder} constructor. 112 */ 113 public static <K, V> Builder<K, V> builder() { 114 return new Builder<K, V>(); 115 } 116 117 /** 118 * A builder for creating immutable bimap instances, especially {@code public 119 * static final} bimaps ("constant bimaps"). Example: <pre> {@code 120 * 121 * static final ImmutableBiMap<String, Integer> WORD_TO_INT = 122 * new ImmutableBiMap.Builder<String, Integer>() 123 * .put("one", 1) 124 * .put("two", 2) 125 * .put("three", 3) 126 * .build();}</pre> 127 * 128 * For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods 129 * are even more convenient. 130 * 131 * <p>Builder instances can be reused - it is safe to call {@link #build} 132 * multiple times to build multiple bimaps in series. Each bimap is a superset 133 * of the bimaps created before it. 134 * 135 * @since 2 (imported from Google Collections Library) 136 */ 137 public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> { 138 139 /** 140 * Creates a new builder. The returned builder is equivalent to the builder 141 * generated by {@link ImmutableBiMap#builder}. 142 */ 143 public Builder() {} 144 145 /** 146 * Associates {@code key} with {@code value} in the built bimap. Duplicate 147 * keys or values are not allowed, and will cause {@link #build} to fail. 148 */ 149 @Override public Builder<K, V> put(K key, V value) { 150 super.put(key, value); 151 return this; 152 } 153 154 /** 155 * Associates all of the given map's keys and values in the built bimap. 156 * Duplicate keys or values are not allowed, and will cause {@link #build} 157 * to fail. 158 * 159 * @throws NullPointerException if any key or value in {@code map} is null 160 */ 161 @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) { 162 super.putAll(map); 163 return this; 164 } 165 166 /** 167 * Returns a newly-created immutable bimap. 168 * 169 * @throws IllegalArgumentException if duplicate keys or values were added 170 */ 171 @Override public ImmutableBiMap<K, V> build() { 172 ImmutableMap<K, V> map = super.build(); 173 if (map.isEmpty()) { 174 return of(); 175 } 176 return new RegularImmutableBiMap<K, V>(map); 177 } 178 } 179 180 /** 181 * Returns an immutable bimap containing the same entries as {@code map}. If 182 * {@code map} somehow contains entries with duplicate keys (for example, if 183 * it is a {@code SortedMap} whose comparator is not <i>consistent with 184 * equals</i>), the results of this method are undefined. 185 * 186 * <p>Despite the method name, this method attempts to avoid actually copying 187 * the data when it is safe to do so. The exact circumstances under which a 188 * copy will or will not be performed are undocumented and subject to change. 189 * 190 * @throws IllegalArgumentException if two keys have the same value 191 * @throws NullPointerException if any key or value in {@code map} is null 192 */ 193 public static <K, V> ImmutableBiMap<K, V> copyOf( 194 Map<? extends K, ? extends V> map) { 195 if (map instanceof ImmutableBiMap) { 196 @SuppressWarnings("unchecked") // safe since map is not writable 197 ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map; 198 // TODO(user): if we need to make a copy of a BiMap because the 199 // forward map is a view, don't make a copy of the non-view delegate map 200 if (!bimap.isPartialView()) { 201 return bimap; 202 } 203 } 204 205 if (map.isEmpty()) { 206 return of(); 207 } 208 209 ImmutableMap<K, V> immutableMap = ImmutableMap.copyOf(map); 210 return new RegularImmutableBiMap<K, V>(immutableMap); 211 } 212 213 ImmutableBiMap() {} 214 215 abstract ImmutableMap<K, V> delegate(); 216 217 /** 218 * {@inheritDoc} 219 * 220 * <p>The inverse of an {@code ImmutableBiMap} is another 221 * {@code ImmutableBiMap}. 222 */ 223 @Override 224 public abstract ImmutableBiMap<V, K> inverse(); 225 226 @Override public boolean containsKey(@Nullable Object key) { 227 return delegate().containsKey(key); 228 } 229 230 @Override public boolean containsValue(@Nullable Object value) { 231 return inverse().containsKey(value); 232 } 233 234 @Override public ImmutableSet<Entry<K, V>> entrySet() { 235 return delegate().entrySet(); 236 } 237 238 @Override public V get(@Nullable Object key) { 239 return delegate().get(key); 240 } 241 242 @Override public ImmutableSet<K> keySet() { 243 return delegate().keySet(); 244 } 245 246 /** 247 * Returns an immutable set of the values in this map. The values are in the 248 * same order as the parameters used to build this map. 249 */ 250 @Override public ImmutableSet<V> values() { 251 return inverse().keySet(); 252 } 253 254 /** 255 * Guaranteed to throw an exception and leave the bimap unmodified. 256 * 257 * @throws UnsupportedOperationException always 258 */ 259 @Override 260 public V forcePut(K key, V value) { 261 throw new UnsupportedOperationException(); 262 } 263 264 @Override public boolean isEmpty() { 265 return delegate().isEmpty(); 266 } 267 268 @Override 269 public int size() { 270 return delegate().size(); 271 } 272 273 @Override public boolean equals(@Nullable Object object) { 274 return object == this || delegate().equals(object); 275 } 276 277 @Override public int hashCode() { 278 return delegate().hashCode(); 279 } 280 281 @Override public String toString() { 282 return delegate().toString(); 283 } 284 285 /** Bimap with no mappings. */ 286 @SuppressWarnings("serial") // uses writeReplace(), not default serialization 287 static class EmptyBiMap extends ImmutableBiMap<Object, Object> { 288 @Override ImmutableMap<Object, Object> delegate() { 289 return ImmutableMap.of(); 290 } 291 @Override public ImmutableBiMap<Object, Object> inverse() { 292 return this; 293 } 294 @Override boolean isPartialView() { 295 return false; 296 } 297 Object readResolve() { 298 return EMPTY_IMMUTABLE_BIMAP; // preserve singleton property 299 } 300 } 301 302 /** 303 * Serialized type for all ImmutableBiMap instances. It captures the logical 304 * contents and they are reconstructed using public factory methods. This 305 * ensures that the implementation types remain as implementation details. 306 * 307 * Since the bimap is immutable, ImmutableBiMap doesn't require special logic 308 * for keeping the bimap and its inverse in sync during serialization, the way 309 * AbstractBiMap does. 310 */ 311 private static class SerializedForm extends ImmutableMap.SerializedForm { 312 SerializedForm(ImmutableBiMap<?, ?> bimap) { 313 super(bimap); 314 } 315 @Override Object readResolve() { 316 Builder<Object, Object> builder = new Builder<Object, Object>(); 317 return createMap(builder); 318 } 319 private static final long serialVersionUID = 0; 320 } 321 322 @Override Object writeReplace() { 323 return new SerializedForm(this); 324 } 325 }