1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* 2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Copyright (C) 2008 The Guava Authors 3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Licensed under the Apache License, Version 2.0 (the "License"); 5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * you may not use this file except in compliance with the License. 6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * You may obtain a copy of the License at 7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * http://www.apache.org/licenses/LICENSE-2.0 9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Unless required by applicable law or agreed to in writing, software 11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * distributed under the License is distributed on an "AS IS" BASIS, 12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * See the License for the specific language governing permissions and 14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * limitations under the License. 15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovpackage com.google.common.collect; 18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport com.google.common.annotations.Beta; 20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport com.google.common.annotations.GwtCompatible; 21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport java.util.Collection; 23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport java.util.Comparator; 24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport java.util.Map.Entry; 25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport javax.annotation.Nullable; 27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/** 29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * An immutable {@link ListMultimap} with reliable user-specified key and value 30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * iteration order. Does not permit null keys or values. 31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p>Unlike {@link Multimaps#unmodifiableListMultimap(ListMultimap)}, which is 33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * a <i>view</i> of a separate multimap which can still change, an instance of 34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@code ImmutableListMultimap} contains its own data and will <i>never</i> 35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * change. {@code ImmutableListMultimap} is convenient for 36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@code public static final} multimaps ("constant multimaps") and also lets 37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * you easily make a "defensive copy" of a multimap provided to your class by 38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * a caller. 39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as 41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * it has no public or protected constructors. Thus, instances of this class 42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * are guaranteed to be immutable. 43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @author Jared Levy 45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @since 2.0 (imported from Google Collections Library) 46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov@GwtCompatible(serializable = true, emulated = true) 48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovpublic class ImmutableListMultimap<K, V> 49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov extends ImmutableMultimap<K, V> 50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov implements ListMultimap<K, V> { 51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** Returns the empty multimap. */ 53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Casting is safe because the multimap will never hold any elements. 54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov @SuppressWarnings("unchecked") 55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public static <K, V> ImmutableListMultimap<K, V> of() { 56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return (ImmutableListMultimap<K, V>) EmptyImmutableListMultimap.INSTANCE; 57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Returns an immutable multimap containing a single entry. 61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1) { 63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ImmutableListMultimap.Builder<K, V> builder 64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = ImmutableListMultimap.builder(); 65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov builder.put(k1, v1); 66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return builder.build(); 67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Returns an immutable multimap containing the given entries, in order. 71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public static <K, V> ImmutableListMultimap<K, V> of(K k1, V v1, K k2, V v2) { 73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ImmutableListMultimap.Builder<K, V> builder 74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = ImmutableListMultimap.builder(); 75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov builder.put(k1, v1); 76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov builder.put(k2, v2); 77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return builder.build(); 78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Returns an immutable multimap containing the given entries, in order. 82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public static <K, V> ImmutableListMultimap<K, V> of( 84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov K k1, V v1, K k2, V v2, K k3, V v3) { 85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ImmutableListMultimap.Builder<K, V> builder 86 = ImmutableListMultimap.builder(); 87 builder.put(k1, v1); 88 builder.put(k2, v2); 89 builder.put(k3, v3); 90 return builder.build(); 91 } 92 93 /** 94 * Returns an immutable multimap containing the given entries, in order. 95 */ 96 public static <K, V> ImmutableListMultimap<K, V> of( 97 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { 98 ImmutableListMultimap.Builder<K, V> builder 99 = ImmutableListMultimap.builder(); 100 builder.put(k1, v1); 101 builder.put(k2, v2); 102 builder.put(k3, v3); 103 builder.put(k4, v4); 104 return builder.build(); 105 } 106 107 /** 108 * Returns an immutable multimap containing the given entries, in order. 109 */ 110 public static <K, V> ImmutableListMultimap<K, V> of( 111 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { 112 ImmutableListMultimap.Builder<K, V> builder 113 = ImmutableListMultimap.builder(); 114 builder.put(k1, v1); 115 builder.put(k2, v2); 116 builder.put(k3, v3); 117 builder.put(k4, v4); 118 builder.put(k5, v5); 119 return builder.build(); 120 } 121 122 // looking for of() with > 5 entries? Use the builder instead. 123 124 /** 125 * Returns a new builder. The generated builder is equivalent to the builder 126 * created by the {@link Builder} constructor. 127 */ 128 public static <K, V> Builder<K, V> builder() { 129 return new Builder<K, V>(); 130 } 131 132 /** 133 * A builder for creating immutable {@code ListMultimap} instances, especially 134 * {@code public static final} multimaps ("constant multimaps"). Example: 135 * <pre> {@code 136 * 137 * static final Multimap<String, Integer> STRING_TO_INTEGER_MULTIMAP = 138 * new ImmutableListMultimap.Builder<String, Integer>() 139 * .put("one", 1) 140 * .putAll("several", 1, 2, 3) 141 * .putAll("many", 1, 2, 3, 4, 5) 142 * .build();}</pre> 143 * 144 * Builder instances can be reused; it is safe to call {@link #build} multiple 145 * times to build multiple multimaps in series. Each multimap contains the 146 * key-value mappings in the previously created multimaps. 147 * 148 * @since 2.0 (imported from Google Collections Library) 149 */ 150 public static final class Builder<K, V> 151 extends ImmutableMultimap.Builder<K, V> { 152 /** 153 * Creates a new builder. The returned builder is equivalent to the builder 154 * generated by {@link ImmutableListMultimap#builder}. 155 */ 156 public Builder() {} 157 158 @Override public Builder<K, V> put(K key, V value) { 159 super.put(key, value); 160 return this; 161 } 162 163 /** 164 * {@inheritDoc} 165 * 166 * @since 11.0 167 */ 168 @Override public Builder<K, V> put( 169 Entry<? extends K, ? extends V> entry) { 170 super.put(entry); 171 return this; 172 } 173 174 @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) { 175 super.putAll(key, values); 176 return this; 177 } 178 179 @Override public Builder<K, V> putAll(K key, V... values) { 180 super.putAll(key, values); 181 return this; 182 } 183 184 @Override public Builder<K, V> putAll( 185 Multimap<? extends K, ? extends V> multimap) { 186 super.putAll(multimap); 187 return this; 188 } 189 190 /** 191 * {@inheritDoc} 192 * 193 * @since 8.0 194 */ 195 @Beta @Override 196 public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) { 197 super.orderKeysBy(keyComparator); 198 return this; 199 } 200 201 /** 202 * {@inheritDoc} 203 * 204 * @since 8.0 205 */ 206 @Beta @Override 207 public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) { 208 super.orderValuesBy(valueComparator); 209 return this; 210 } 211 212 /** 213 * Returns a newly-created immutable list multimap. 214 */ 215 @Override public ImmutableListMultimap<K, V> build() { 216 return (ImmutableListMultimap<K, V>) super.build(); 217 } 218 } 219 220 /** 221 * Returns an immutable multimap containing the same mappings as {@code 222 * multimap}. The generated multimap's key and value orderings correspond to 223 * the iteration ordering of the {@code multimap.asMap()} view. 224 * 225 * <p>Despite the method name, this method attempts to avoid actually copying 226 * the data when it is safe to do so. The exact circumstances under which a 227 * copy will or will not be performed are undocumented and subject to change. 228 * 229 * @throws NullPointerException if any key or value in {@code multimap} is 230 * null 231 */ 232 public static <K, V> ImmutableListMultimap<K, V> copyOf( 233 Multimap<? extends K, ? extends V> multimap) { 234 if (multimap.isEmpty()) { 235 return of(); 236 } 237 238 // TODO(user): copy ImmutableSetMultimap by using asList() on the sets 239 if (multimap instanceof ImmutableListMultimap) { 240 @SuppressWarnings("unchecked") // safe since multimap is not writable 241 ImmutableListMultimap<K, V> kvMultimap 242 = (ImmutableListMultimap<K, V>) multimap; 243 if (!kvMultimap.isPartialView()) { 244 return kvMultimap; 245 } 246 } 247 248 ImmutableMap.Builder<K, ImmutableList<V>> builder = ImmutableMap.builder(); 249 int size = 0; 250 251 for (Entry<? extends K, ? extends Collection<? extends V>> entry 252 : multimap.asMap().entrySet()) { 253 ImmutableList<V> list = ImmutableList.copyOf(entry.getValue()); 254 if (!list.isEmpty()) { 255 builder.put(entry.getKey(), list); 256 size += list.size(); 257 } 258 } 259 260 return new ImmutableListMultimap<K, V>(builder.build(), size); 261 } 262 263 ImmutableListMultimap(ImmutableMap<K, ImmutableList<V>> map, int size) { 264 super(map, size); 265 } 266 267 // views 268 269 /** 270 * Returns an immutable list of the values for the given key. If no mappings 271 * in the multimap have the provided key, an empty immutable list is 272 * returned. The values are in the same order as the parameters used to build 273 * this multimap. 274 */ 275 @Override public ImmutableList<V> get(@Nullable K key) { 276 // This cast is safe as its type is known in constructor. 277 ImmutableList<V> list = (ImmutableList<V>) map.get(key); 278 return (list == null) ? ImmutableList.<V>of() : list; 279 } 280 281 private transient ImmutableListMultimap<V, K> inverse; 282 283 /** 284 * {@inheritDoc} 285 * 286 * <p>Because an inverse of a list multimap can contain multiple pairs with the same key and 287 * value, this method returns an {@code ImmutableListMultimap} rather than the 288 * {@code ImmutableMultimap} specified in the {@code ImmutableMultimap} class. 289 * 290 * @since 11 291 */ 292 @Beta 293 public ImmutableListMultimap<V, K> inverse() { 294 ImmutableListMultimap<V, K> result = inverse; 295 return (result == null) ? (inverse = invert()) : result; 296 } 297 298 private ImmutableListMultimap<V, K> invert() { 299 Builder<V, K> builder = builder(); 300 for (Entry<K, V> entry : entries()) { 301 builder.put(entry.getValue(), entry.getKey()); 302 } 303 ImmutableListMultimap<V, K> invertedMultimap = builder.build(); 304 invertedMultimap.inverse = this; 305 return invertedMultimap; 306 } 307 308 /** 309 * Guaranteed to throw an exception and leave the multimap unmodified. 310 * 311 * @throws UnsupportedOperationException always 312 */ 313 @Override public ImmutableList<V> removeAll(Object key) { 314 throw new UnsupportedOperationException(); 315 } 316 317 /** 318 * Guaranteed to throw an exception and leave the multimap unmodified. 319 * 320 * @throws UnsupportedOperationException always 321 */ 322 @Override public ImmutableList<V> replaceValues( 323 K key, Iterable<? extends V> values) { 324 throw new UnsupportedOperationException(); 325 } 326} 327