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.GwtCompatible; 020 021import java.util.Map; 022 023/** 024 * An immutable {@link BiMap} with reliable user-specified iteration order. Does 025 * not permit null keys or values. An {@code ImmutableBiMap} and its inverse 026 * have the same iteration ordering. 027 * 028 * <p>An instance of {@code ImmutableBiMap} contains its own data and will 029 * <i>never</i> change. {@code ImmutableBiMap} is convenient for 030 * {@code public static final} maps ("constant maps") and also lets you easily 031 * make a "defensive copy" of a bimap provided to your class by a caller. 032 * 033 * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as 034 * it has no public or protected constructors. Thus, instances of this class are 035 * guaranteed to be immutable. 036 * 037 * @author Jared Levy 038 * @since 2.0 (imported from Google Collections Library) 039 */ 040@GwtCompatible(serializable = true, emulated = true) 041public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> 042 implements BiMap<K, V> { 043 044 /** 045 * Returns the empty bimap. 046 */ 047 // Casting to any type is safe because the set will never hold any elements. 048 @SuppressWarnings("unchecked") 049 public static <K, V> ImmutableBiMap<K, V> of() { 050 return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE; 051 } 052 053 /** 054 * Returns an immutable bimap containing a single entry. 055 */ 056 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) { 057 return new SingletonImmutableBiMap<K, V>(k1, v1); 058 } 059 060 /** 061 * Returns an immutable map containing the given entries, in order. 062 * 063 * @throws IllegalArgumentException if duplicate keys or values are added 064 */ 065 public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) { 066 return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2)); 067 } 068 069 /** 070 * Returns an immutable map containing the given entries, in order. 071 * 072 * @throws IllegalArgumentException if duplicate keys or values are added 073 */ 074 public static <K, V> ImmutableBiMap<K, V> of( 075 K k1, V v1, K k2, V v2, K k3, V v3) { 076 return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3)); 077 } 078 079 /** 080 * Returns an immutable map containing the given entries, in order. 081 * 082 * @throws IllegalArgumentException if duplicate keys or values are added 083 */ 084 public static <K, V> ImmutableBiMap<K, V> of( 085 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 086 return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), 087 entryOf(k4, v4)); 088 } 089 090 /** 091 * Returns an immutable map containing the given entries, in order. 092 * 093 * @throws IllegalArgumentException if duplicate keys or values are added 094 */ 095 public static <K, V> ImmutableBiMap<K, V> of( 096 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 097 return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), 098 entryOf(k4, v4), entryOf(k5, v5)); 099 } 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}