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.0 (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 /** 047 * Returns the empty bimap. 048 */ 049 // Casting to any type is safe because the set will never hold any elements. 050 @SuppressWarnings("unchecked") 051 public static <K, V> ImmutableBiMap<K, V> of() { 052 return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE; 053 } 054 055 /** 056 * Returns an immutable bimap containing a single entry. 057 */ 058 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) { 059 return new RegularImmutableBiMap<K, V>(ImmutableMap.of(k1, v1)); 060 } 061 062 /** 063 * Returns an immutable map containing the given entries, in order. 064 * 065 * @throws IllegalArgumentException if duplicate keys or values are added 066 */ 067 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) { 068 return new RegularImmutableBiMap<K, V>(ImmutableMap.of(k1, v1, k2, v2)); 069 } 070 071 /** 072 * Returns an immutable map containing the given entries, in order. 073 * 074 * @throws IllegalArgumentException if duplicate keys or values are added 075 */ 076 public static <K, V> ImmutableBiMap<K, V> of( 077 K k1, V v1, K k2, V v2, K k3, V v3) { 078 return new RegularImmutableBiMap<K, V>(ImmutableMap.of( 079 k1, v1, k2, v2, k3, v3)); 080 } 081 082 /** 083 * Returns an immutable map containing the given entries, in order. 084 * 085 * @throws IllegalArgumentException if duplicate keys or values are added 086 */ 087 public static <K, V> ImmutableBiMap<K, V> of( 088 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 089 return new RegularImmutableBiMap<K, V>(ImmutableMap.of( 090 k1, v1, k2, v2, k3, v3, k4, v4)); 091 } 092 093 /** 094 * Returns an immutable map containing the given entries, in order. 095 * 096 * @throws IllegalArgumentException if duplicate keys or values are added 097 */ 098 public static <K, V> ImmutableBiMap<K, V> of( 099 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 100 return new RegularImmutableBiMap<K, V>(ImmutableMap.of( 101 k1, v1, k2, v2, k3, v3, k4, v4, k5, v5)); 102 } 103 104 // looking for of() with > 5 entries? Use the builder instead. 105 106 /** 107 * Returns a new builder. The generated builder is equivalent to the builder 108 * created by the {@link Builder} constructor. 109 */ 110 public static <K, V> Builder<K, V> builder() { 111 return new Builder<K, V>(); 112 } 113 114 /** 115 * A builder for creating immutable bimap instances, especially {@code public 116 * static final} bimaps ("constant bimaps"). Example: <pre> {@code 117 * 118 * static final ImmutableBiMap<String, Integer> WORD_TO_INT = 119 * new ImmutableBiMap.Builder<String, Integer>() 120 * .put("one", 1) 121 * .put("two", 2) 122 * .put("three", 3) 123 * .build();}</pre> 124 * 125 * For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods 126 * are even more convenient. 127 * 128 * <p>Builder instances can be reused - it is safe to call {@link #build} 129 * multiple times to build multiple bimaps in series. Each bimap is a superset 130 * of the bimaps created before it. 131 * 132 * @since 2.0 (imported from Google Collections Library) 133 */ 134 public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> { 135 136 /** 137 * Creates a new builder. The returned builder is equivalent to the builder 138 * generated by {@link ImmutableBiMap#builder}. 139 */ 140 public Builder() {} 141 142 /** 143 * Associates {@code key} with {@code value} in the built bimap. Duplicate 144 * keys or values are not allowed, and will cause {@link #build} to fail. 145 */ 146 @Override public Builder<K, V> put(K key, V value) { 147 super.put(key, value); 148 return this; 149 } 150 151 /** 152 * Associates all of the given map's keys and values in the built bimap. 153 * Duplicate keys or values are not allowed, and will cause {@link #build} 154 * to fail. 155 * 156 * @throws NullPointerException if any key or value in {@code map} is null 157 */ 158 @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) { 159 super.putAll(map); 160 return this; 161 } 162 163 /** 164 * Returns a newly-created immutable bimap. 165 * 166 * @throws IllegalArgumentException if duplicate keys or values were added 167 */ 168 @Override public ImmutableBiMap<K, V> build() { 169 ImmutableMap<K, V> map = super.build(); 170 if (map.isEmpty()) { 171 return of(); 172 } 173 return new RegularImmutableBiMap<K, V>(map); 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 202 if (map.isEmpty()) { 203 return of(); 204 } 205 206 ImmutableMap<K, V> immutableMap = ImmutableMap.copyOf(map); 207 return new RegularImmutableBiMap<K, V>(immutableMap); 208 } 209 210 ImmutableBiMap() {} 211 212 abstract ImmutableMap<K, V> delegate(); 213 214 /** 215 * {@inheritDoc} 216 * 217 * <p>The inverse of an {@code ImmutableBiMap} is another 218 * {@code ImmutableBiMap}. 219 */ 220 @Override 221 public abstract ImmutableBiMap<V, K> inverse(); 222 223 @Override public boolean containsKey(@Nullable Object key) { 224 return delegate().containsKey(key); 225 } 226 227 @Override public boolean containsValue(@Nullable Object value) { 228 return inverse().containsKey(value); 229 } 230 231 @Override ImmutableSet<Entry<K, V>> createEntrySet() { 232 return delegate().entrySet(); 233 } 234 235 @Override public V get(@Nullable Object key) { 236 return delegate().get(key); 237 } 238 239 @Override public ImmutableSet<K> keySet() { 240 return delegate().keySet(); 241 } 242 243 /** 244 * Returns an immutable set of the values in this map. The values are in the 245 * same order as the parameters used to build this map. 246 */ 247 @Override public ImmutableSet<V> values() { 248 return inverse().keySet(); 249 } 250 251 /** 252 * Guaranteed to throw an exception and leave the bimap unmodified. 253 * 254 * @throws UnsupportedOperationException always 255 */ 256 @Override 257 public V forcePut(K key, V value) { 258 throw new UnsupportedOperationException(); 259 } 260 261 @Override public boolean isEmpty() { 262 return delegate().isEmpty(); 263 } 264 265 @Override 266 public int size() { 267 return delegate().size(); 268 } 269 270 @Override public boolean equals(@Nullable Object object) { 271 return object == this || delegate().equals(object); 272 } 273 274 @Override public int hashCode() { 275 return delegate().hashCode(); 276 } 277 278 @Override public String toString() { 279 return delegate().toString(); 280 } 281 282 /** 283 * Serialized type for all ImmutableBiMap instances. It captures the logical 284 * contents and they are reconstructed using public factory methods. This 285 * ensures that the implementation types remain as implementation details. 286 * 287 * Since the bimap is immutable, ImmutableBiMap doesn't require special logic 288 * for keeping the bimap and its inverse in sync during serialization, the way 289 * AbstractBiMap does. 290 */ 291 private static class SerializedForm extends ImmutableMap.SerializedForm { 292 SerializedForm(ImmutableBiMap<?, ?> bimap) { 293 super(bimap); 294 } 295 @Override Object readResolve() { 296 Builder<Object, Object> builder = new Builder<Object, Object>(); 297 return createMap(builder); 298 } 299 private static final long serialVersionUID = 0; 300 } 301 302 @Override Object writeReplace() { 303 return new SerializedForm(this); 304 } 305 }