1 /* 2 * Copyright (C) 2007 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 static com.google.common.base.Preconditions.checkNotNull; 20 import static com.google.common.collect.CollectPreconditions.checkNonnegative; 21 import static com.google.common.collect.CollectPreconditions.checkRemove; 22 23 import com.google.common.annotations.Beta; 24 import com.google.common.annotations.GwtCompatible; 25 import com.google.common.annotations.GwtIncompatible; 26 import com.google.common.base.Function; 27 import com.google.common.base.Predicate; 28 import com.google.common.base.Predicates; 29 import com.google.common.base.Supplier; 30 import com.google.common.collect.Maps.EntryTransformer; 31 import com.google.errorprone.annotations.CanIgnoreReturnValue; 32 import com.google.j2objc.annotations.Weak; 33 import com.google.j2objc.annotations.WeakOuter; 34 import java.io.IOException; 35 import java.io.ObjectInputStream; 36 import java.io.ObjectOutputStream; 37 import java.io.Serializable; 38 import java.util.AbstractCollection; 39 import java.util.Collection; 40 import java.util.Collections; 41 import java.util.Comparator; 42 import java.util.HashSet; 43 import java.util.Iterator; 44 import java.util.List; 45 import java.util.Map; 46 import java.util.Map.Entry; 47 import java.util.NavigableSet; 48 import java.util.NoSuchElementException; 49 import java.util.Set; 50 import java.util.SortedSet; 51 import org.checkerframework.checker.nullness.compatqual.NullableDecl; 52 53 /** 54 * Provides static methods acting on or generating a {@code Multimap}. 55 * 56 * <p>See the Guava User Guide article on <a href= 57 * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multimaps"> {@code 58 * Multimaps}</a>. 59 * 60 * @author Jared Levy 61 * @author Robert Konigsberg 62 * @author Mike Bostock 63 * @author Louis Wasserman 64 * @since 2.0 65 */ 66 @GwtCompatible(emulated = true) 67 public final class Multimaps { Multimaps()68 private Multimaps() {} 69 70 /** 71 * Creates a new {@code Multimap} backed by {@code map}, whose internal value collections are 72 * generated by {@code factory}. 73 * 74 * <p><b>Warning: do not use</b> this method when the collections returned by {@code factory} 75 * implement either {@link List} or {@code Set}! Use the more specific method {@link 76 * #newListMultimap}, {@link #newSetMultimap} or {@link #newSortedSetMultimap} instead, to avoid 77 * very surprising behavior from {@link Multimap#equals}. 78 * 79 * <p>The {@code factory}-generated and {@code map} classes determine the multimap iteration 80 * order. They also specify the behavior of the {@code equals}, {@code hashCode}, and {@code 81 * toString} methods for the multimap and its returned views. However, the multimap's {@code get} 82 * method returns instances of a different class than {@code factory.get()} does. 83 * 84 * <p>The multimap is serializable if {@code map}, {@code factory}, the collections generated by 85 * {@code factory}, and the multimap contents are all serializable. 86 * 87 * <p>The multimap is not threadsafe when any concurrent operations update the multimap, even if 88 * {@code map} and the instances generated by {@code factory} are. Concurrent read operations will 89 * work correctly. To allow concurrent update operations, wrap the multimap with a call to {@link 90 * #synchronizedMultimap}. 91 * 92 * <p>Call this method only when the simpler methods {@link ArrayListMultimap#create()}, {@link 93 * HashMultimap#create()}, {@link LinkedHashMultimap#create()}, {@link 94 * LinkedListMultimap#create()}, {@link TreeMultimap#create()}, and {@link 95 * TreeMultimap#create(Comparator, Comparator)} won't suffice. 96 * 97 * <p>Note: the multimap assumes complete ownership over of {@code map} and the collections 98 * returned by {@code factory}. Those objects should not be manually updated and they should not 99 * use soft, weak, or phantom references. 100 * 101 * @param map place to store the mapping from each key to its corresponding values 102 * @param factory supplier of new, empty collections that will each hold all values for a given 103 * key 104 * @throws IllegalArgumentException if {@code map} is not empty 105 */ newMultimap( Map<K, Collection<V>> map, final Supplier<? extends Collection<V>> factory)106 public static <K, V> Multimap<K, V> newMultimap( 107 Map<K, Collection<V>> map, final Supplier<? extends Collection<V>> factory) { 108 return new CustomMultimap<>(map, factory); 109 } 110 111 private static class CustomMultimap<K, V> extends AbstractMapBasedMultimap<K, V> { 112 transient Supplier<? extends Collection<V>> factory; 113 CustomMultimap(Map<K, Collection<V>> map, Supplier<? extends Collection<V>> factory)114 CustomMultimap(Map<K, Collection<V>> map, Supplier<? extends Collection<V>> factory) { 115 super(map); 116 this.factory = checkNotNull(factory); 117 } 118 119 @Override createKeySet()120 Set<K> createKeySet() { 121 return createMaybeNavigableKeySet(); 122 } 123 124 @Override createAsMap()125 Map<K, Collection<V>> createAsMap() { 126 return createMaybeNavigableAsMap(); 127 } 128 129 @Override createCollection()130 protected Collection<V> createCollection() { 131 return factory.get(); 132 } 133 134 @Override unmodifiableCollectionSubclass(Collection<E> collection)135 <E> Collection<E> unmodifiableCollectionSubclass(Collection<E> collection) { 136 if (collection instanceof NavigableSet) { 137 return Sets.unmodifiableNavigableSet((NavigableSet<E>) collection); 138 } else if (collection instanceof SortedSet) { 139 return Collections.unmodifiableSortedSet((SortedSet<E>) collection); 140 } else if (collection instanceof Set) { 141 return Collections.unmodifiableSet((Set<E>) collection); 142 } else if (collection instanceof List) { 143 return Collections.unmodifiableList((List<E>) collection); 144 } else { 145 return Collections.unmodifiableCollection(collection); 146 } 147 } 148 149 @Override wrapCollection(K key, Collection<V> collection)150 Collection<V> wrapCollection(K key, Collection<V> collection) { 151 if (collection instanceof List) { 152 return wrapList(key, (List<V>) collection, null); 153 } else if (collection instanceof NavigableSet) { 154 return new WrappedNavigableSet(key, (NavigableSet<V>) collection, null); 155 } else if (collection instanceof SortedSet) { 156 return new WrappedSortedSet(key, (SortedSet<V>) collection, null); 157 } else if (collection instanceof Set) { 158 return new WrappedSet(key, (Set<V>) collection); 159 } else { 160 return new WrappedCollection(key, collection, null); 161 } 162 } 163 164 // can't use Serialization writeMultimap and populateMultimap methods since 165 // there's no way to generate the empty backing map. 166 167 /** @serialData the factory and the backing map */ 168 @GwtIncompatible // java.io.ObjectOutputStream writeObject(ObjectOutputStream stream)169 private void writeObject(ObjectOutputStream stream) throws IOException { 170 stream.defaultWriteObject(); 171 stream.writeObject(factory); 172 stream.writeObject(backingMap()); 173 } 174 175 @GwtIncompatible // java.io.ObjectInputStream 176 @SuppressWarnings("unchecked") // reading data stored by writeObject readObject(ObjectInputStream stream)177 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 178 stream.defaultReadObject(); 179 factory = (Supplier<? extends Collection<V>>) stream.readObject(); 180 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); 181 setMap(map); 182 } 183 184 @GwtIncompatible // java serialization not supported 185 private static final long serialVersionUID = 0; 186 } 187 188 /** 189 * Creates a new {@code ListMultimap} that uses the provided map and factory. It can generate a 190 * multimap based on arbitrary {@link Map} and {@link List} classes. 191 * 192 * <p>The {@code factory}-generated and {@code map} classes determine the multimap iteration 193 * order. They also specify the behavior of the {@code equals}, {@code hashCode}, and {@code 194 * toString} methods for the multimap and its returned views. The multimap's {@code get}, {@code 195 * removeAll}, and {@code replaceValues} methods return {@code RandomAccess} lists if the factory 196 * does. However, the multimap's {@code get} method returns instances of a different class than 197 * does {@code factory.get()}. 198 * 199 * <p>The multimap is serializable if {@code map}, {@code factory}, the lists generated by {@code 200 * factory}, and the multimap contents are all serializable. 201 * 202 * <p>The multimap is not threadsafe when any concurrent operations update the multimap, even if 203 * {@code map} and the instances generated by {@code factory} are. Concurrent read operations will 204 * work correctly. To allow concurrent update operations, wrap the multimap with a call to {@link 205 * #synchronizedListMultimap}. 206 * 207 * <p>Call this method only when the simpler methods {@link ArrayListMultimap#create()} and {@link 208 * LinkedListMultimap#create()} won't suffice. 209 * 210 * <p>Note: the multimap assumes complete ownership over of {@code map} and the lists returned by 211 * {@code factory}. Those objects should not be manually updated, they should be empty when 212 * provided, and they should not use soft, weak, or phantom references. 213 * 214 * @param map place to store the mapping from each key to its corresponding values 215 * @param factory supplier of new, empty lists that will each hold all values for a given key 216 * @throws IllegalArgumentException if {@code map} is not empty 217 */ newListMultimap( Map<K, Collection<V>> map, final Supplier<? extends List<V>> factory)218 public static <K, V> ListMultimap<K, V> newListMultimap( 219 Map<K, Collection<V>> map, final Supplier<? extends List<V>> factory) { 220 return new CustomListMultimap<>(map, factory); 221 } 222 223 private static class CustomListMultimap<K, V> extends AbstractListMultimap<K, V> { 224 transient Supplier<? extends List<V>> factory; 225 CustomListMultimap(Map<K, Collection<V>> map, Supplier<? extends List<V>> factory)226 CustomListMultimap(Map<K, Collection<V>> map, Supplier<? extends List<V>> factory) { 227 super(map); 228 this.factory = checkNotNull(factory); 229 } 230 231 @Override createKeySet()232 Set<K> createKeySet() { 233 return createMaybeNavigableKeySet(); 234 } 235 236 @Override createAsMap()237 Map<K, Collection<V>> createAsMap() { 238 return createMaybeNavigableAsMap(); 239 } 240 241 @Override createCollection()242 protected List<V> createCollection() { 243 return factory.get(); 244 } 245 246 /** @serialData the factory and the backing map */ 247 @GwtIncompatible // java.io.ObjectOutputStream writeObject(ObjectOutputStream stream)248 private void writeObject(ObjectOutputStream stream) throws IOException { 249 stream.defaultWriteObject(); 250 stream.writeObject(factory); 251 stream.writeObject(backingMap()); 252 } 253 254 @GwtIncompatible // java.io.ObjectInputStream 255 @SuppressWarnings("unchecked") // reading data stored by writeObject readObject(ObjectInputStream stream)256 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 257 stream.defaultReadObject(); 258 factory = (Supplier<? extends List<V>>) stream.readObject(); 259 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); 260 setMap(map); 261 } 262 263 @GwtIncompatible // java serialization not supported 264 private static final long serialVersionUID = 0; 265 } 266 267 /** 268 * Creates a new {@code SetMultimap} that uses the provided map and factory. It can generate a 269 * multimap based on arbitrary {@link Map} and {@link Set} classes. 270 * 271 * <p>The {@code factory}-generated and {@code map} classes determine the multimap iteration 272 * order. They also specify the behavior of the {@code equals}, {@code hashCode}, and {@code 273 * toString} methods for the multimap and its returned views. However, the multimap's {@code get} 274 * method returns instances of a different class than {@code factory.get()} does. 275 * 276 * <p>The multimap is serializable if {@code map}, {@code factory}, the sets generated by {@code 277 * factory}, and the multimap contents are all serializable. 278 * 279 * <p>The multimap is not threadsafe when any concurrent operations update the multimap, even if 280 * {@code map} and the instances generated by {@code factory} are. Concurrent read operations will 281 * work correctly. To allow concurrent update operations, wrap the multimap with a call to {@link 282 * #synchronizedSetMultimap}. 283 * 284 * <p>Call this method only when the simpler methods {@link HashMultimap#create()}, {@link 285 * LinkedHashMultimap#create()}, {@link TreeMultimap#create()}, and {@link 286 * TreeMultimap#create(Comparator, Comparator)} won't suffice. 287 * 288 * <p>Note: the multimap assumes complete ownership over of {@code map} and the sets returned by 289 * {@code factory}. Those objects should not be manually updated and they should not use soft, 290 * weak, or phantom references. 291 * 292 * @param map place to store the mapping from each key to its corresponding values 293 * @param factory supplier of new, empty sets that will each hold all values for a given key 294 * @throws IllegalArgumentException if {@code map} is not empty 295 */ newSetMultimap( Map<K, Collection<V>> map, final Supplier<? extends Set<V>> factory)296 public static <K, V> SetMultimap<K, V> newSetMultimap( 297 Map<K, Collection<V>> map, final Supplier<? extends Set<V>> factory) { 298 return new CustomSetMultimap<>(map, factory); 299 } 300 301 private static class CustomSetMultimap<K, V> extends AbstractSetMultimap<K, V> { 302 transient Supplier<? extends Set<V>> factory; 303 CustomSetMultimap(Map<K, Collection<V>> map, Supplier<? extends Set<V>> factory)304 CustomSetMultimap(Map<K, Collection<V>> map, Supplier<? extends Set<V>> factory) { 305 super(map); 306 this.factory = checkNotNull(factory); 307 } 308 309 @Override createKeySet()310 Set<K> createKeySet() { 311 return createMaybeNavigableKeySet(); 312 } 313 314 @Override createAsMap()315 Map<K, Collection<V>> createAsMap() { 316 return createMaybeNavigableAsMap(); 317 } 318 319 @Override createCollection()320 protected Set<V> createCollection() { 321 return factory.get(); 322 } 323 324 @Override unmodifiableCollectionSubclass(Collection<E> collection)325 <E> Collection<E> unmodifiableCollectionSubclass(Collection<E> collection) { 326 if (collection instanceof NavigableSet) { 327 return Sets.unmodifiableNavigableSet((NavigableSet<E>) collection); 328 } else if (collection instanceof SortedSet) { 329 return Collections.unmodifiableSortedSet((SortedSet<E>) collection); 330 } else { 331 return Collections.unmodifiableSet((Set<E>) collection); 332 } 333 } 334 335 @Override wrapCollection(K key, Collection<V> collection)336 Collection<V> wrapCollection(K key, Collection<V> collection) { 337 if (collection instanceof NavigableSet) { 338 return new WrappedNavigableSet(key, (NavigableSet<V>) collection, null); 339 } else if (collection instanceof SortedSet) { 340 return new WrappedSortedSet(key, (SortedSet<V>) collection, null); 341 } else { 342 return new WrappedSet(key, (Set<V>) collection); 343 } 344 } 345 346 /** @serialData the factory and the backing map */ 347 @GwtIncompatible // java.io.ObjectOutputStream writeObject(ObjectOutputStream stream)348 private void writeObject(ObjectOutputStream stream) throws IOException { 349 stream.defaultWriteObject(); 350 stream.writeObject(factory); 351 stream.writeObject(backingMap()); 352 } 353 354 @GwtIncompatible // java.io.ObjectInputStream 355 @SuppressWarnings("unchecked") // reading data stored by writeObject readObject(ObjectInputStream stream)356 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 357 stream.defaultReadObject(); 358 factory = (Supplier<? extends Set<V>>) stream.readObject(); 359 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); 360 setMap(map); 361 } 362 363 @GwtIncompatible // not needed in emulated source 364 private static final long serialVersionUID = 0; 365 } 366 367 /** 368 * Creates a new {@code SortedSetMultimap} that uses the provided map and factory. It can generate 369 * a multimap based on arbitrary {@link Map} and {@link SortedSet} classes. 370 * 371 * <p>The {@code factory}-generated and {@code map} classes determine the multimap iteration 372 * order. They also specify the behavior of the {@code equals}, {@code hashCode}, and {@code 373 * toString} methods for the multimap and its returned views. However, the multimap's {@code get} 374 * method returns instances of a different class than {@code factory.get()} does. 375 * 376 * <p>The multimap is serializable if {@code map}, {@code factory}, the sets generated by {@code 377 * factory}, and the multimap contents are all serializable. 378 * 379 * <p>The multimap is not threadsafe when any concurrent operations update the multimap, even if 380 * {@code map} and the instances generated by {@code factory} are. Concurrent read operations will 381 * work correctly. To allow concurrent update operations, wrap the multimap with a call to {@link 382 * #synchronizedSortedSetMultimap}. 383 * 384 * <p>Call this method only when the simpler methods {@link TreeMultimap#create()} and {@link 385 * TreeMultimap#create(Comparator, Comparator)} won't suffice. 386 * 387 * <p>Note: the multimap assumes complete ownership over of {@code map} and the sets returned by 388 * {@code factory}. Those objects should not be manually updated and they should not use soft, 389 * weak, or phantom references. 390 * 391 * @param map place to store the mapping from each key to its corresponding values 392 * @param factory supplier of new, empty sorted sets that will each hold all values for a given 393 * key 394 * @throws IllegalArgumentException if {@code map} is not empty 395 */ newSortedSetMultimap( Map<K, Collection<V>> map, final Supplier<? extends SortedSet<V>> factory)396 public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap( 397 Map<K, Collection<V>> map, final Supplier<? extends SortedSet<V>> factory) { 398 return new CustomSortedSetMultimap<>(map, factory); 399 } 400 401 private static class CustomSortedSetMultimap<K, V> extends AbstractSortedSetMultimap<K, V> { 402 transient Supplier<? extends SortedSet<V>> factory; 403 transient Comparator<? super V> valueComparator; 404 CustomSortedSetMultimap(Map<K, Collection<V>> map, Supplier<? extends SortedSet<V>> factory)405 CustomSortedSetMultimap(Map<K, Collection<V>> map, Supplier<? extends SortedSet<V>> factory) { 406 super(map); 407 this.factory = checkNotNull(factory); 408 valueComparator = factory.get().comparator(); 409 } 410 411 @Override createKeySet()412 Set<K> createKeySet() { 413 return createMaybeNavigableKeySet(); 414 } 415 416 @Override createAsMap()417 Map<K, Collection<V>> createAsMap() { 418 return createMaybeNavigableAsMap(); 419 } 420 421 @Override createCollection()422 protected SortedSet<V> createCollection() { 423 return factory.get(); 424 } 425 426 @Override valueComparator()427 public Comparator<? super V> valueComparator() { 428 return valueComparator; 429 } 430 431 /** @serialData the factory and the backing map */ 432 @GwtIncompatible // java.io.ObjectOutputStream writeObject(ObjectOutputStream stream)433 private void writeObject(ObjectOutputStream stream) throws IOException { 434 stream.defaultWriteObject(); 435 stream.writeObject(factory); 436 stream.writeObject(backingMap()); 437 } 438 439 @GwtIncompatible // java.io.ObjectInputStream 440 @SuppressWarnings("unchecked") // reading data stored by writeObject readObject(ObjectInputStream stream)441 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 442 stream.defaultReadObject(); 443 factory = (Supplier<? extends SortedSet<V>>) stream.readObject(); 444 valueComparator = factory.get().comparator(); 445 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); 446 setMap(map); 447 } 448 449 @GwtIncompatible // not needed in emulated source 450 private static final long serialVersionUID = 0; 451 } 452 453 /** 454 * Copies each key-value mapping in {@code source} into {@code dest}, with its key and value 455 * reversed. 456 * 457 * <p>If {@code source} is an {@link ImmutableMultimap}, consider using {@link 458 * ImmutableMultimap#inverse} instead. 459 * 460 * @param source any multimap 461 * @param dest the multimap to copy into; usually empty 462 * @return {@code dest} 463 */ 464 @CanIgnoreReturnValue invertFrom( Multimap<? extends V, ? extends K> source, M dest)465 public static <K, V, M extends Multimap<K, V>> M invertFrom( 466 Multimap<? extends V, ? extends K> source, M dest) { 467 checkNotNull(dest); 468 for (Map.Entry<? extends V, ? extends K> entry : source.entries()) { 469 dest.put(entry.getValue(), entry.getKey()); 470 } 471 return dest; 472 } 473 474 /** 475 * Returns a synchronized (thread-safe) multimap backed by the specified multimap. In order to 476 * guarantee serial access, it is critical that <b>all</b> access to the backing multimap is 477 * accomplished through the returned multimap. 478 * 479 * <p>It is imperative that the user manually synchronize on the returned multimap when accessing 480 * any of its collection views: 481 * 482 * <pre>{@code 483 * Multimap<K, V> multimap = Multimaps.synchronizedMultimap( 484 * HashMultimap.<K, V>create()); 485 * ... 486 * Collection<V> values = multimap.get(key); // Needn't be in synchronized block 487 * ... 488 * synchronized (multimap) { // Synchronizing on multimap, not values! 489 * Iterator<V> i = values.iterator(); // Must be in synchronized block 490 * while (i.hasNext()) { 491 * foo(i.next()); 492 * } 493 * } 494 * }</pre> 495 * 496 * <p>Failure to follow this advice may result in non-deterministic behavior. 497 * 498 * <p>Note that the generated multimap's {@link Multimap#removeAll} and {@link 499 * Multimap#replaceValues} methods return collections that aren't synchronized. 500 * 501 * <p>The returned multimap will be serializable if the specified multimap is serializable. 502 * 503 * @param multimap the multimap to be wrapped in a synchronized view 504 * @return a synchronized view of the specified multimap 505 */ synchronizedMultimap(Multimap<K, V> multimap)506 public static <K, V> Multimap<K, V> synchronizedMultimap(Multimap<K, V> multimap) { 507 return Synchronized.multimap(multimap, null); 508 } 509 510 /** 511 * Returns an unmodifiable view of the specified multimap. Query operations on the returned 512 * multimap "read through" to the specified multimap, and attempts to modify the returned 513 * multimap, either directly or through the multimap's views, result in an {@code 514 * UnsupportedOperationException}. 515 * 516 * <p>The returned multimap will be serializable if the specified multimap is serializable. 517 * 518 * @param delegate the multimap for which an unmodifiable view is to be returned 519 * @return an unmodifiable view of the specified multimap 520 */ unmodifiableMultimap(Multimap<K, V> delegate)521 public static <K, V> Multimap<K, V> unmodifiableMultimap(Multimap<K, V> delegate) { 522 if (delegate instanceof UnmodifiableMultimap || delegate instanceof ImmutableMultimap) { 523 return delegate; 524 } 525 return new UnmodifiableMultimap<>(delegate); 526 } 527 528 /** 529 * Simply returns its argument. 530 * 531 * @deprecated no need to use this 532 * @since 10.0 533 */ 534 @Deprecated unmodifiableMultimap(ImmutableMultimap<K, V> delegate)535 public static <K, V> Multimap<K, V> unmodifiableMultimap(ImmutableMultimap<K, V> delegate) { 536 return checkNotNull(delegate); 537 } 538 539 private static class UnmodifiableMultimap<K, V> extends ForwardingMultimap<K, V> 540 implements Serializable { 541 final Multimap<K, V> delegate; 542 @NullableDecl transient Collection<Entry<K, V>> entries; 543 @NullableDecl transient Multiset<K> keys; 544 @NullableDecl transient Set<K> keySet; 545 @NullableDecl transient Collection<V> values; 546 @NullableDecl transient Map<K, Collection<V>> map; 547 UnmodifiableMultimap(final Multimap<K, V> delegate)548 UnmodifiableMultimap(final Multimap<K, V> delegate) { 549 this.delegate = checkNotNull(delegate); 550 } 551 552 @Override delegate()553 protected Multimap<K, V> delegate() { 554 return delegate; 555 } 556 557 @Override clear()558 public void clear() { 559 throw new UnsupportedOperationException(); 560 } 561 562 @Override asMap()563 public Map<K, Collection<V>> asMap() { 564 Map<K, Collection<V>> result = map; 565 if (result == null) { 566 result = 567 map = 568 Collections.unmodifiableMap( 569 Maps.transformValues( 570 delegate.asMap(), 571 new Function<Collection<V>, Collection<V>>() { 572 @Override 573 public Collection<V> apply(Collection<V> collection) { 574 return unmodifiableValueCollection(collection); 575 } 576 })); 577 } 578 return result; 579 } 580 581 @Override entries()582 public Collection<Entry<K, V>> entries() { 583 Collection<Entry<K, V>> result = entries; 584 if (result == null) { 585 entries = result = unmodifiableEntries(delegate.entries()); 586 } 587 return result; 588 } 589 590 @Override get(K key)591 public Collection<V> get(K key) { 592 return unmodifiableValueCollection(delegate.get(key)); 593 } 594 595 @Override keys()596 public Multiset<K> keys() { 597 Multiset<K> result = keys; 598 if (result == null) { 599 keys = result = Multisets.unmodifiableMultiset(delegate.keys()); 600 } 601 return result; 602 } 603 604 @Override keySet()605 public Set<K> keySet() { 606 Set<K> result = keySet; 607 if (result == null) { 608 keySet = result = Collections.unmodifiableSet(delegate.keySet()); 609 } 610 return result; 611 } 612 613 @Override put(K key, V value)614 public boolean put(K key, V value) { 615 throw new UnsupportedOperationException(); 616 } 617 618 @Override putAll(K key, Iterable<? extends V> values)619 public boolean putAll(K key, Iterable<? extends V> values) { 620 throw new UnsupportedOperationException(); 621 } 622 623 @Override putAll(Multimap<? extends K, ? extends V> multimap)624 public boolean putAll(Multimap<? extends K, ? extends V> multimap) { 625 throw new UnsupportedOperationException(); 626 } 627 628 @Override remove(Object key, Object value)629 public boolean remove(Object key, Object value) { 630 throw new UnsupportedOperationException(); 631 } 632 633 @Override removeAll(Object key)634 public Collection<V> removeAll(Object key) { 635 throw new UnsupportedOperationException(); 636 } 637 638 @Override replaceValues(K key, Iterable<? extends V> values)639 public Collection<V> replaceValues(K key, Iterable<? extends V> values) { 640 throw new UnsupportedOperationException(); 641 } 642 643 @Override values()644 public Collection<V> values() { 645 Collection<V> result = values; 646 if (result == null) { 647 values = result = Collections.unmodifiableCollection(delegate.values()); 648 } 649 return result; 650 } 651 652 private static final long serialVersionUID = 0; 653 } 654 655 private static class UnmodifiableListMultimap<K, V> extends UnmodifiableMultimap<K, V> 656 implements ListMultimap<K, V> { UnmodifiableListMultimap(ListMultimap<K, V> delegate)657 UnmodifiableListMultimap(ListMultimap<K, V> delegate) { 658 super(delegate); 659 } 660 661 @Override delegate()662 public ListMultimap<K, V> delegate() { 663 return (ListMultimap<K, V>) super.delegate(); 664 } 665 666 @Override get(K key)667 public List<V> get(K key) { 668 return Collections.unmodifiableList(delegate().get(key)); 669 } 670 671 @Override removeAll(Object key)672 public List<V> removeAll(Object key) { 673 throw new UnsupportedOperationException(); 674 } 675 676 @Override replaceValues(K key, Iterable<? extends V> values)677 public List<V> replaceValues(K key, Iterable<? extends V> values) { 678 throw new UnsupportedOperationException(); 679 } 680 681 private static final long serialVersionUID = 0; 682 } 683 684 private static class UnmodifiableSetMultimap<K, V> extends UnmodifiableMultimap<K, V> 685 implements SetMultimap<K, V> { UnmodifiableSetMultimap(SetMultimap<K, V> delegate)686 UnmodifiableSetMultimap(SetMultimap<K, V> delegate) { 687 super(delegate); 688 } 689 690 @Override delegate()691 public SetMultimap<K, V> delegate() { 692 return (SetMultimap<K, V>) super.delegate(); 693 } 694 695 @Override get(K key)696 public Set<V> get(K key) { 697 /* 698 * Note that this doesn't return a SortedSet when delegate is a 699 * SortedSetMultiset, unlike (SortedSet<V>) super.get(). 700 */ 701 return Collections.unmodifiableSet(delegate().get(key)); 702 } 703 704 @Override entries()705 public Set<Map.Entry<K, V>> entries() { 706 return Maps.unmodifiableEntrySet(delegate().entries()); 707 } 708 709 @Override removeAll(Object key)710 public Set<V> removeAll(Object key) { 711 throw new UnsupportedOperationException(); 712 } 713 714 @Override replaceValues(K key, Iterable<? extends V> values)715 public Set<V> replaceValues(K key, Iterable<? extends V> values) { 716 throw new UnsupportedOperationException(); 717 } 718 719 private static final long serialVersionUID = 0; 720 } 721 722 private static class UnmodifiableSortedSetMultimap<K, V> extends UnmodifiableSetMultimap<K, V> 723 implements SortedSetMultimap<K, V> { UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate)724 UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate) { 725 super(delegate); 726 } 727 728 @Override delegate()729 public SortedSetMultimap<K, V> delegate() { 730 return (SortedSetMultimap<K, V>) super.delegate(); 731 } 732 733 @Override get(K key)734 public SortedSet<V> get(K key) { 735 return Collections.unmodifiableSortedSet(delegate().get(key)); 736 } 737 738 @Override removeAll(Object key)739 public SortedSet<V> removeAll(Object key) { 740 throw new UnsupportedOperationException(); 741 } 742 743 @Override replaceValues(K key, Iterable<? extends V> values)744 public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) { 745 throw new UnsupportedOperationException(); 746 } 747 748 @Override valueComparator()749 public Comparator<? super V> valueComparator() { 750 return delegate().valueComparator(); 751 } 752 753 private static final long serialVersionUID = 0; 754 } 755 756 /** 757 * Returns a synchronized (thread-safe) {@code SetMultimap} backed by the specified multimap. 758 * 759 * <p>You must follow the warnings described in {@link #synchronizedMultimap}. 760 * 761 * <p>The returned multimap will be serializable if the specified multimap is serializable. 762 * 763 * @param multimap the multimap to be wrapped 764 * @return a synchronized view of the specified multimap 765 */ synchronizedSetMultimap(SetMultimap<K, V> multimap)766 public static <K, V> SetMultimap<K, V> synchronizedSetMultimap(SetMultimap<K, V> multimap) { 767 return Synchronized.setMultimap(multimap, null); 768 } 769 770 /** 771 * Returns an unmodifiable view of the specified {@code SetMultimap}. Query operations on the 772 * returned multimap "read through" to the specified multimap, and attempts to modify the returned 773 * multimap, either directly or through the multimap's views, result in an {@code 774 * UnsupportedOperationException}. 775 * 776 * <p>The returned multimap will be serializable if the specified multimap is serializable. 777 * 778 * @param delegate the multimap for which an unmodifiable view is to be returned 779 * @return an unmodifiable view of the specified multimap 780 */ unmodifiableSetMultimap(SetMultimap<K, V> delegate)781 public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap(SetMultimap<K, V> delegate) { 782 if (delegate instanceof UnmodifiableSetMultimap || delegate instanceof ImmutableSetMultimap) { 783 return delegate; 784 } 785 return new UnmodifiableSetMultimap<>(delegate); 786 } 787 788 /** 789 * Simply returns its argument. 790 * 791 * @deprecated no need to use this 792 * @since 10.0 793 */ 794 @Deprecated unmodifiableSetMultimap( ImmutableSetMultimap<K, V> delegate)795 public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap( 796 ImmutableSetMultimap<K, V> delegate) { 797 return checkNotNull(delegate); 798 } 799 800 /** 801 * Returns a synchronized (thread-safe) {@code SortedSetMultimap} backed by the specified 802 * multimap. 803 * 804 * <p>You must follow the warnings described in {@link #synchronizedMultimap}. 805 * 806 * <p>The returned multimap will be serializable if the specified multimap is serializable. 807 * 808 * @param multimap the multimap to be wrapped 809 * @return a synchronized view of the specified multimap 810 */ synchronizedSortedSetMultimap( SortedSetMultimap<K, V> multimap)811 public static <K, V> SortedSetMultimap<K, V> synchronizedSortedSetMultimap( 812 SortedSetMultimap<K, V> multimap) { 813 return Synchronized.sortedSetMultimap(multimap, null); 814 } 815 816 /** 817 * Returns an unmodifiable view of the specified {@code SortedSetMultimap}. Query operations on 818 * the returned multimap "read through" to the specified multimap, and attempts to modify the 819 * returned multimap, either directly or through the multimap's views, result in an {@code 820 * UnsupportedOperationException}. 821 * 822 * <p>The returned multimap will be serializable if the specified multimap is serializable. 823 * 824 * @param delegate the multimap for which an unmodifiable view is to be returned 825 * @return an unmodifiable view of the specified multimap 826 */ unmodifiableSortedSetMultimap( SortedSetMultimap<K, V> delegate)827 public static <K, V> SortedSetMultimap<K, V> unmodifiableSortedSetMultimap( 828 SortedSetMultimap<K, V> delegate) { 829 if (delegate instanceof UnmodifiableSortedSetMultimap) { 830 return delegate; 831 } 832 return new UnmodifiableSortedSetMultimap<>(delegate); 833 } 834 835 /** 836 * Returns a synchronized (thread-safe) {@code ListMultimap} backed by the specified multimap. 837 * 838 * <p>You must follow the warnings described in {@link #synchronizedMultimap}. 839 * 840 * @param multimap the multimap to be wrapped 841 * @return a synchronized view of the specified multimap 842 */ synchronizedListMultimap(ListMultimap<K, V> multimap)843 public static <K, V> ListMultimap<K, V> synchronizedListMultimap(ListMultimap<K, V> multimap) { 844 return Synchronized.listMultimap(multimap, null); 845 } 846 847 /** 848 * Returns an unmodifiable view of the specified {@code ListMultimap}. Query operations on the 849 * returned multimap "read through" to the specified multimap, and attempts to modify the returned 850 * multimap, either directly or through the multimap's views, result in an {@code 851 * UnsupportedOperationException}. 852 * 853 * <p>The returned multimap will be serializable if the specified multimap is serializable. 854 * 855 * @param delegate the multimap for which an unmodifiable view is to be returned 856 * @return an unmodifiable view of the specified multimap 857 */ unmodifiableListMultimap(ListMultimap<K, V> delegate)858 public static <K, V> ListMultimap<K, V> unmodifiableListMultimap(ListMultimap<K, V> delegate) { 859 if (delegate instanceof UnmodifiableListMultimap || delegate instanceof ImmutableListMultimap) { 860 return delegate; 861 } 862 return new UnmodifiableListMultimap<>(delegate); 863 } 864 865 /** 866 * Simply returns its argument. 867 * 868 * @deprecated no need to use this 869 * @since 10.0 870 */ 871 @Deprecated unmodifiableListMultimap( ImmutableListMultimap<K, V> delegate)872 public static <K, V> ListMultimap<K, V> unmodifiableListMultimap( 873 ImmutableListMultimap<K, V> delegate) { 874 return checkNotNull(delegate); 875 } 876 877 /** 878 * Returns an unmodifiable view of the specified collection, preserving the interface for 879 * instances of {@code SortedSet}, {@code Set}, {@code List} and {@code Collection}, in that order 880 * of preference. 881 * 882 * @param collection the collection for which to return an unmodifiable view 883 * @return an unmodifiable view of the collection 884 */ unmodifiableValueCollection(Collection<V> collection)885 private static <V> Collection<V> unmodifiableValueCollection(Collection<V> collection) { 886 if (collection instanceof SortedSet) { 887 return Collections.unmodifiableSortedSet((SortedSet<V>) collection); 888 } else if (collection instanceof Set) { 889 return Collections.unmodifiableSet((Set<V>) collection); 890 } else if (collection instanceof List) { 891 return Collections.unmodifiableList((List<V>) collection); 892 } 893 return Collections.unmodifiableCollection(collection); 894 } 895 896 /** 897 * Returns an unmodifiable view of the specified collection of entries. The {@link Entry#setValue} 898 * operation throws an {@link UnsupportedOperationException}. If the specified collection is a 899 * {@code Set}, the returned collection is also a {@code Set}. 900 * 901 * @param entries the entries for which to return an unmodifiable view 902 * @return an unmodifiable view of the entries 903 */ unmodifiableEntries( Collection<Entry<K, V>> entries)904 private static <K, V> Collection<Entry<K, V>> unmodifiableEntries( 905 Collection<Entry<K, V>> entries) { 906 if (entries instanceof Set) { 907 return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries); 908 } 909 return new Maps.UnmodifiableEntries<>(Collections.unmodifiableCollection(entries)); 910 } 911 912 /** 913 * Returns {@link ListMultimap#asMap multimap.asMap()}, with its type corrected from {@code Map<K, 914 * Collection<V>>} to {@code Map<K, List<V>>}. 915 * 916 * @since 15.0 917 */ 918 @Beta 919 @SuppressWarnings("unchecked") 920 // safe by specification of ListMultimap.asMap() asMap(ListMultimap<K, V> multimap)921 public static <K, V> Map<K, List<V>> asMap(ListMultimap<K, V> multimap) { 922 return (Map<K, List<V>>) (Map<K, ?>) multimap.asMap(); 923 } 924 925 /** 926 * Returns {@link SetMultimap#asMap multimap.asMap()}, with its type corrected from {@code Map<K, 927 * Collection<V>>} to {@code Map<K, Set<V>>}. 928 * 929 * @since 15.0 930 */ 931 @Beta 932 @SuppressWarnings("unchecked") 933 // safe by specification of SetMultimap.asMap() asMap(SetMultimap<K, V> multimap)934 public static <K, V> Map<K, Set<V>> asMap(SetMultimap<K, V> multimap) { 935 return (Map<K, Set<V>>) (Map<K, ?>) multimap.asMap(); 936 } 937 938 /** 939 * Returns {@link SortedSetMultimap#asMap multimap.asMap()}, with its type corrected from {@code 940 * Map<K, Collection<V>>} to {@code Map<K, SortedSet<V>>}. 941 * 942 * @since 15.0 943 */ 944 @Beta 945 @SuppressWarnings("unchecked") 946 // safe by specification of SortedSetMultimap.asMap() asMap(SortedSetMultimap<K, V> multimap)947 public static <K, V> Map<K, SortedSet<V>> asMap(SortedSetMultimap<K, V> multimap) { 948 return (Map<K, SortedSet<V>>) (Map<K, ?>) multimap.asMap(); 949 } 950 951 /** 952 * Returns {@link Multimap#asMap multimap.asMap()}. This is provided for parity with the other 953 * more strongly-typed {@code asMap()} implementations. 954 * 955 * @since 15.0 956 */ 957 @Beta asMap(Multimap<K, V> multimap)958 public static <K, V> Map<K, Collection<V>> asMap(Multimap<K, V> multimap) { 959 return multimap.asMap(); 960 } 961 962 /** 963 * Returns a multimap view of the specified map. The multimap is backed by the map, so changes to 964 * the map are reflected in the multimap, and vice versa. If the map is modified while an 965 * iteration over one of the multimap's collection views is in progress (except through the 966 * iterator's own {@code remove} operation, or through the {@code setValue} operation on a map 967 * entry returned by the iterator), the results of the iteration are undefined. 968 * 969 * <p>The multimap supports mapping removal, which removes the corresponding mapping from the map. 970 * It does not support any operations which might add mappings, such as {@code put}, {@code 971 * putAll} or {@code replaceValues}. 972 * 973 * <p>The returned multimap will be serializable if the specified map is serializable. 974 * 975 * @param map the backing map for the returned multimap view 976 */ forMap(Map<K, V> map)977 public static <K, V> SetMultimap<K, V> forMap(Map<K, V> map) { 978 return new MapMultimap<>(map); 979 } 980 981 /** @see Multimaps#forMap */ 982 private static class MapMultimap<K, V> extends AbstractMultimap<K, V> 983 implements SetMultimap<K, V>, Serializable { 984 final Map<K, V> map; 985 MapMultimap(Map<K, V> map)986 MapMultimap(Map<K, V> map) { 987 this.map = checkNotNull(map); 988 } 989 990 @Override size()991 public int size() { 992 return map.size(); 993 } 994 995 @Override containsKey(Object key)996 public boolean containsKey(Object key) { 997 return map.containsKey(key); 998 } 999 1000 @Override containsValue(Object value)1001 public boolean containsValue(Object value) { 1002 return map.containsValue(value); 1003 } 1004 1005 @Override containsEntry(Object key, Object value)1006 public boolean containsEntry(Object key, Object value) { 1007 return map.entrySet().contains(Maps.immutableEntry(key, value)); 1008 } 1009 1010 @Override get(final K key)1011 public Set<V> get(final K key) { 1012 return new Sets.ImprovedAbstractSet<V>() { 1013 @Override 1014 public Iterator<V> iterator() { 1015 return new Iterator<V>() { 1016 int i; 1017 1018 @Override 1019 public boolean hasNext() { 1020 return (i == 0) && map.containsKey(key); 1021 } 1022 1023 @Override 1024 public V next() { 1025 if (!hasNext()) { 1026 throw new NoSuchElementException(); 1027 } 1028 i++; 1029 return map.get(key); 1030 } 1031 1032 @Override 1033 public void remove() { 1034 checkRemove(i == 1); 1035 i = -1; 1036 map.remove(key); 1037 } 1038 }; 1039 } 1040 1041 @Override 1042 public int size() { 1043 return map.containsKey(key) ? 1 : 0; 1044 } 1045 }; 1046 } 1047 1048 @Override 1049 public boolean put(K key, V value) { 1050 throw new UnsupportedOperationException(); 1051 } 1052 1053 @Override 1054 public boolean putAll(K key, Iterable<? extends V> values) { 1055 throw new UnsupportedOperationException(); 1056 } 1057 1058 @Override 1059 public boolean putAll(Multimap<? extends K, ? extends V> multimap) { 1060 throw new UnsupportedOperationException(); 1061 } 1062 1063 @Override 1064 public Set<V> replaceValues(K key, Iterable<? extends V> values) { 1065 throw new UnsupportedOperationException(); 1066 } 1067 1068 @Override 1069 public boolean remove(Object key, Object value) { 1070 return map.entrySet().remove(Maps.immutableEntry(key, value)); 1071 } 1072 1073 @Override 1074 public Set<V> removeAll(Object key) { 1075 Set<V> values = new HashSet<V>(2); 1076 if (!map.containsKey(key)) { 1077 return values; 1078 } 1079 values.add(map.remove(key)); 1080 return values; 1081 } 1082 1083 @Override 1084 public void clear() { 1085 map.clear(); 1086 } 1087 1088 @Override 1089 Set<K> createKeySet() { 1090 return map.keySet(); 1091 } 1092 1093 @Override 1094 Collection<V> createValues() { 1095 return map.values(); 1096 } 1097 1098 @Override 1099 public Set<Entry<K, V>> entries() { 1100 return map.entrySet(); 1101 } 1102 1103 @Override 1104 Collection<Entry<K, V>> createEntries() { 1105 throw new AssertionError("unreachable"); 1106 } 1107 1108 @Override 1109 Multiset<K> createKeys() { 1110 return new Multimaps.Keys<K, V>(this); 1111 } 1112 1113 @Override 1114 Iterator<Entry<K, V>> entryIterator() { 1115 return map.entrySet().iterator(); 1116 } 1117 1118 @Override 1119 Map<K, Collection<V>> createAsMap() { 1120 return new AsMap<>(this); 1121 } 1122 1123 @Override 1124 public int hashCode() { 1125 return map.hashCode(); 1126 } 1127 1128 private static final long serialVersionUID = 7845222491160860175L; 1129 } 1130 1131 /** 1132 * Returns a view of a multimap where each value is transformed by a function. All other 1133 * properties of the multimap, such as iteration order, are left intact. For example, the code: 1134 * 1135 * <pre>{@code 1136 * Multimap<String, Integer> multimap = 1137 * ImmutableSetMultimap.of("a", 2, "b", -3, "b", -3, "a", 4, "c", 6); 1138 * Function<Integer, String> square = new Function<Integer, String>() { 1139 * public String apply(Integer in) { 1140 * return Integer.toString(in * in); 1141 * } 1142 * }; 1143 * Multimap<String, String> transformed = 1144 * Multimaps.transformValues(multimap, square); 1145 * System.out.println(transformed); 1146 * }</pre> 1147 * 1148 * ... prints {@code {a=[4, 16], b=[9, 9], c=[36]}}. 1149 * 1150 * <p>Changes in the underlying multimap are reflected in this view. Conversely, this view 1151 * supports removal operations, and these are reflected in the underlying multimap. 1152 * 1153 * <p>It's acceptable for the underlying multimap to contain null keys, and even null values 1154 * provided that the function is capable of accepting null input. The transformed multimap might 1155 * contain null values, if the function sometimes gives a null result. 1156 * 1157 * <p>The returned multimap is not thread-safe or serializable, even if the underlying multimap 1158 * is. The {@code equals} and {@code hashCode} methods of the returned multimap are meaningless, 1159 * since there is not a definition of {@code equals} or {@code hashCode} for general collections, 1160 * and {@code get()} will return a general {@code Collection} as opposed to a {@code List} or a 1161 * {@code Set}. 1162 * 1163 * <p>The function is applied lazily, invoked when needed. This is necessary for the returned 1164 * multimap to be a view, but it means that the function will be applied many times for bulk 1165 * operations like {@link Multimap#containsValue} and {@code Multimap.toString()}. For this to 1166 * perform well, {@code function} should be fast. To avoid lazy evaluation when the returned 1167 * multimap doesn't need to be a view, copy the returned multimap into a new multimap of your 1168 * choosing. 1169 * 1170 * @since 7.0 1171 */ 1172 public static <K, V1, V2> Multimap<K, V2> transformValues( 1173 Multimap<K, V1> fromMultimap, final Function<? super V1, V2> function) { 1174 checkNotNull(function); 1175 EntryTransformer<K, V1, V2> transformer = Maps.asEntryTransformer(function); 1176 return transformEntries(fromMultimap, transformer); 1177 } 1178 1179 /** 1180 * Returns a view of a {@code ListMultimap} where each value is transformed by a function. All 1181 * other properties of the multimap, such as iteration order, are left intact. For example, the 1182 * code: 1183 * 1184 * <pre>{@code 1185 * ListMultimap<String, Integer> multimap 1186 * = ImmutableListMultimap.of("a", 4, "a", 16, "b", 9); 1187 * Function<Integer, Double> sqrt = 1188 * new Function<Integer, Double>() { 1189 * public Double apply(Integer in) { 1190 * return Math.sqrt((int) in); 1191 * } 1192 * }; 1193 * ListMultimap<String, Double> transformed = Multimaps.transformValues(map, 1194 * sqrt); 1195 * System.out.println(transformed); 1196 * }</pre> 1197 * 1198 * ... prints {@code {a=[2.0, 4.0], b=[3.0]}}. 1199 * 1200 * <p>Changes in the underlying multimap are reflected in this view. Conversely, this view 1201 * supports removal operations, and these are reflected in the underlying multimap. 1202 * 1203 * <p>It's acceptable for the underlying multimap to contain null keys, and even null values 1204 * provided that the function is capable of accepting null input. The transformed multimap might 1205 * contain null values, if the function sometimes gives a null result. 1206 * 1207 * <p>The returned multimap is not thread-safe or serializable, even if the underlying multimap 1208 * is. 1209 * 1210 * <p>The function is applied lazily, invoked when needed. This is necessary for the returned 1211 * multimap to be a view, but it means that the function will be applied many times for bulk 1212 * operations like {@link Multimap#containsValue} and {@code Multimap.toString()}. For this to 1213 * perform well, {@code function} should be fast. To avoid lazy evaluation when the returned 1214 * multimap doesn't need to be a view, copy the returned multimap into a new multimap of your 1215 * choosing. 1216 * 1217 * @since 7.0 1218 */ 1219 public static <K, V1, V2> ListMultimap<K, V2> transformValues( 1220 ListMultimap<K, V1> fromMultimap, final Function<? super V1, V2> function) { 1221 checkNotNull(function); 1222 EntryTransformer<K, V1, V2> transformer = Maps.asEntryTransformer(function); 1223 return transformEntries(fromMultimap, transformer); 1224 } 1225 1226 /** 1227 * Returns a view of a multimap whose values are derived from the original multimap's entries. In 1228 * contrast to {@link #transformValues}, this method's entry-transformation logic may depend on 1229 * the key as well as the value. 1230 * 1231 * <p>All other properties of the transformed multimap, such as iteration order, are left intact. 1232 * For example, the code: 1233 * 1234 * <pre>{@code 1235 * SetMultimap<String, Integer> multimap = 1236 * ImmutableSetMultimap.of("a", 1, "a", 4, "b", -6); 1237 * EntryTransformer<String, Integer, String> transformer = 1238 * new EntryTransformer<String, Integer, String>() { 1239 * public String transformEntry(String key, Integer value) { 1240 * return (value >= 0) ? key : "no" + key; 1241 * } 1242 * }; 1243 * Multimap<String, String> transformed = 1244 * Multimaps.transformEntries(multimap, transformer); 1245 * System.out.println(transformed); 1246 * }</pre> 1247 * 1248 * ... prints {@code {a=[a, a], b=[nob]}}. 1249 * 1250 * <p>Changes in the underlying multimap are reflected in this view. Conversely, this view 1251 * supports removal operations, and these are reflected in the underlying multimap. 1252 * 1253 * <p>It's acceptable for the underlying multimap to contain null keys and null values provided 1254 * that the transformer is capable of accepting null inputs. The transformed multimap might 1255 * contain null values if the transformer sometimes gives a null result. 1256 * 1257 * <p>The returned multimap is not thread-safe or serializable, even if the underlying multimap 1258 * is. The {@code equals} and {@code hashCode} methods of the returned multimap are meaningless, 1259 * since there is not a definition of {@code equals} or {@code hashCode} for general collections, 1260 * and {@code get()} will return a general {@code Collection} as opposed to a {@code List} or a 1261 * {@code Set}. 1262 * 1263 * <p>The transformer is applied lazily, invoked when needed. This is necessary for the returned 1264 * multimap to be a view, but it means that the transformer will be applied many times for bulk 1265 * operations like {@link Multimap#containsValue} and {@link Object#toString}. For this to perform 1266 * well, {@code transformer} should be fast. To avoid lazy evaluation when the returned multimap 1267 * doesn't need to be a view, copy the returned multimap into a new multimap of your choosing. 1268 * 1269 * <p><b>Warning:</b> This method assumes that for any instance {@code k} of {@code 1270 * EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies that {@code k2} is also of 1271 * type {@code K}. Using an {@code EntryTransformer} key type for which this may not hold, such as 1272 * {@code ArrayList}, may risk a {@code ClassCastException} when calling methods on the 1273 * transformed multimap. 1274 * 1275 * @since 7.0 1276 */ 1277 public static <K, V1, V2> Multimap<K, V2> transformEntries( 1278 Multimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) { 1279 return new TransformedEntriesMultimap<>(fromMap, transformer); 1280 } 1281 1282 /** 1283 * Returns a view of a {@code ListMultimap} whose values are derived from the original multimap's 1284 * entries. In contrast to {@link #transformValues(ListMultimap, Function)}, this method's 1285 * entry-transformation logic may depend on the key as well as the value. 1286 * 1287 * <p>All other properties of the transformed multimap, such as iteration order, are left intact. 1288 * For example, the code: 1289 * 1290 * <pre>{@code 1291 * Multimap<String, Integer> multimap = 1292 * ImmutableMultimap.of("a", 1, "a", 4, "b", 6); 1293 * EntryTransformer<String, Integer, String> transformer = 1294 * new EntryTransformer<String, Integer, String>() { 1295 * public String transformEntry(String key, Integer value) { 1296 * return key + value; 1297 * } 1298 * }; 1299 * Multimap<String, String> transformed = 1300 * Multimaps.transformEntries(multimap, transformer); 1301 * System.out.println(transformed); 1302 * }</pre> 1303 * 1304 * ... prints {@code {"a"=["a1", "a4"], "b"=["b6"]}}. 1305 * 1306 * <p>Changes in the underlying multimap are reflected in this view. Conversely, this view 1307 * supports removal operations, and these are reflected in the underlying multimap. 1308 * 1309 * <p>It's acceptable for the underlying multimap to contain null keys and null values provided 1310 * that the transformer is capable of accepting null inputs. The transformed multimap might 1311 * contain null values if the transformer sometimes gives a null result. 1312 * 1313 * <p>The returned multimap is not thread-safe or serializable, even if the underlying multimap 1314 * is. 1315 * 1316 * <p>The transformer is applied lazily, invoked when needed. This is necessary for the returned 1317 * multimap to be a view, but it means that the transformer will be applied many times for bulk 1318 * operations like {@link Multimap#containsValue} and {@link Object#toString}. For this to perform 1319 * well, {@code transformer} should be fast. To avoid lazy evaluation when the returned multimap 1320 * doesn't need to be a view, copy the returned multimap into a new multimap of your choosing. 1321 * 1322 * <p><b>Warning:</b> This method assumes that for any instance {@code k} of {@code 1323 * EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies that {@code k2} is also of 1324 * type {@code K}. Using an {@code EntryTransformer} key type for which this may not hold, such as 1325 * {@code ArrayList}, may risk a {@code ClassCastException} when calling methods on the 1326 * transformed multimap. 1327 * 1328 * @since 7.0 1329 */ 1330 public static <K, V1, V2> ListMultimap<K, V2> transformEntries( 1331 ListMultimap<K, V1> fromMap, EntryTransformer<? super K, ? super V1, V2> transformer) { 1332 return new TransformedEntriesListMultimap<>(fromMap, transformer); 1333 } 1334 1335 private static class TransformedEntriesMultimap<K, V1, V2> extends AbstractMultimap<K, V2> { 1336 final Multimap<K, V1> fromMultimap; 1337 final EntryTransformer<? super K, ? super V1, V2> transformer; 1338 1339 TransformedEntriesMultimap( 1340 Multimap<K, V1> fromMultimap, 1341 final EntryTransformer<? super K, ? super V1, V2> transformer) { 1342 this.fromMultimap = checkNotNull(fromMultimap); 1343 this.transformer = checkNotNull(transformer); 1344 } 1345 1346 Collection<V2> transform(K key, Collection<V1> values) { 1347 Function<? super V1, V2> function = Maps.asValueToValueFunction(transformer, key); 1348 if (values instanceof List) { 1349 return Lists.transform((List<V1>) values, function); 1350 } else { 1351 return Collections2.transform(values, function); 1352 } 1353 } 1354 1355 @Override 1356 Map<K, Collection<V2>> createAsMap() { 1357 return Maps.transformEntries( 1358 fromMultimap.asMap(), 1359 new EntryTransformer<K, Collection<V1>, Collection<V2>>() { 1360 @Override 1361 public Collection<V2> transformEntry(K key, Collection<V1> value) { 1362 return transform(key, value); 1363 } 1364 }); 1365 } 1366 1367 @Override 1368 public void clear() { 1369 fromMultimap.clear(); 1370 } 1371 1372 @Override 1373 public boolean containsKey(Object key) { 1374 return fromMultimap.containsKey(key); 1375 } 1376 1377 @Override 1378 Collection<Entry<K, V2>> createEntries() { 1379 return new Entries(); 1380 } 1381 1382 @Override 1383 Iterator<Entry<K, V2>> entryIterator() { 1384 return Iterators.transform( 1385 fromMultimap.entries().iterator(), Maps.<K, V1, V2>asEntryToEntryFunction(transformer)); 1386 } 1387 1388 @Override 1389 public Collection<V2> get(final K key) { 1390 return transform(key, fromMultimap.get(key)); 1391 } 1392 1393 @Override 1394 public boolean isEmpty() { 1395 return fromMultimap.isEmpty(); 1396 } 1397 1398 @Override 1399 Set<K> createKeySet() { 1400 return fromMultimap.keySet(); 1401 } 1402 1403 @Override 1404 Multiset<K> createKeys() { 1405 return fromMultimap.keys(); 1406 } 1407 1408 @Override 1409 public boolean put(K key, V2 value) { 1410 throw new UnsupportedOperationException(); 1411 } 1412 1413 @Override 1414 public boolean putAll(K key, Iterable<? extends V2> values) { 1415 throw new UnsupportedOperationException(); 1416 } 1417 1418 @Override 1419 public boolean putAll(Multimap<? extends K, ? extends V2> multimap) { 1420 throw new UnsupportedOperationException(); 1421 } 1422 1423 @SuppressWarnings("unchecked") 1424 @Override 1425 public boolean remove(Object key, Object value) { 1426 return get((K) key).remove(value); 1427 } 1428 1429 @SuppressWarnings("unchecked") 1430 @Override 1431 public Collection<V2> removeAll(Object key) { 1432 return transform((K) key, fromMultimap.removeAll(key)); 1433 } 1434 1435 @Override 1436 public Collection<V2> replaceValues(K key, Iterable<? extends V2> values) { 1437 throw new UnsupportedOperationException(); 1438 } 1439 1440 @Override 1441 public int size() { 1442 return fromMultimap.size(); 1443 } 1444 1445 @Override 1446 Collection<V2> createValues() { 1447 return Collections2.transform( 1448 fromMultimap.entries(), Maps.<K, V1, V2>asEntryToValueFunction(transformer)); 1449 } 1450 } 1451 1452 private static final class TransformedEntriesListMultimap<K, V1, V2> 1453 extends TransformedEntriesMultimap<K, V1, V2> implements ListMultimap<K, V2> { 1454 1455 TransformedEntriesListMultimap( 1456 ListMultimap<K, V1> fromMultimap, EntryTransformer<? super K, ? super V1, V2> transformer) { 1457 super(fromMultimap, transformer); 1458 } 1459 1460 @Override 1461 List<V2> transform(K key, Collection<V1> values) { 1462 return Lists.transform((List<V1>) values, Maps.asValueToValueFunction(transformer, key)); 1463 } 1464 1465 @Override 1466 public List<V2> get(K key) { 1467 return transform(key, fromMultimap.get(key)); 1468 } 1469 1470 @SuppressWarnings("unchecked") 1471 @Override 1472 public List<V2> removeAll(Object key) { 1473 return transform((K) key, fromMultimap.removeAll(key)); 1474 } 1475 1476 @Override 1477 public List<V2> replaceValues(K key, Iterable<? extends V2> values) { 1478 throw new UnsupportedOperationException(); 1479 } 1480 } 1481 1482 /** 1483 * Creates an index {@code ImmutableListMultimap} that contains the results of applying a 1484 * specified function to each item in an {@code Iterable} of values. Each value will be stored as 1485 * a value in the resulting multimap, yielding a multimap with the same size as the input 1486 * iterable. The key used to store that value in the multimap will be the result of calling the 1487 * function on that value. The resulting multimap is created as an immutable snapshot. In the 1488 * returned multimap, keys appear in the order they are first encountered, and the values 1489 * corresponding to each key appear in the same order as they are encountered. 1490 * 1491 * <p>For example, 1492 * 1493 * <pre>{@code 1494 * List<String> badGuys = 1495 * Arrays.asList("Inky", "Blinky", "Pinky", "Pinky", "Clyde"); 1496 * Function<String, Integer> stringLengthFunction = ...; 1497 * Multimap<Integer, String> index = 1498 * Multimaps.index(badGuys, stringLengthFunction); 1499 * System.out.println(index); 1500 * }</pre> 1501 * 1502 * <p>prints 1503 * 1504 * <pre>{@code 1505 * {4=[Inky], 6=[Blinky], 5=[Pinky, Pinky, Clyde]} 1506 * }</pre> 1507 * 1508 * <p>The returned multimap is serializable if its keys and values are all serializable. 1509 * 1510 * @param values the values to use when constructing the {@code ImmutableListMultimap} 1511 * @param keyFunction the function used to produce the key for each value 1512 * @return {@code ImmutableListMultimap} mapping the result of evaluating the function {@code 1513 * keyFunction} on each value in the input collection to that value 1514 * @throws NullPointerException if any element of {@code values} is {@code null}, or if {@code 1515 * keyFunction} produces {@code null} for any key 1516 */ 1517 public static <K, V> ImmutableListMultimap<K, V> index( 1518 Iterable<V> values, Function<? super V, K> keyFunction) { 1519 return index(values.iterator(), keyFunction); 1520 } 1521 1522 /** 1523 * Creates an index {@code ImmutableListMultimap} that contains the results of applying a 1524 * specified function to each item in an {@code Iterator} of values. Each value will be stored as 1525 * a value in the resulting multimap, yielding a multimap with the same size as the input 1526 * iterator. The key used to store that value in the multimap will be the result of calling the 1527 * function on that value. The resulting multimap is created as an immutable snapshot. In the 1528 * returned multimap, keys appear in the order they are first encountered, and the values 1529 * corresponding to each key appear in the same order as they are encountered. 1530 * 1531 * <p>For example, 1532 * 1533 * <pre>{@code 1534 * List<String> badGuys = 1535 * Arrays.asList("Inky", "Blinky", "Pinky", "Pinky", "Clyde"); 1536 * Function<String, Integer> stringLengthFunction = ...; 1537 * Multimap<Integer, String> index = 1538 * Multimaps.index(badGuys.iterator(), stringLengthFunction); 1539 * System.out.println(index); 1540 * }</pre> 1541 * 1542 * <p>prints 1543 * 1544 * <pre>{@code 1545 * {4=[Inky], 6=[Blinky], 5=[Pinky, Pinky, Clyde]} 1546 * }</pre> 1547 * 1548 * <p>The returned multimap is serializable if its keys and values are all serializable. 1549 * 1550 * @param values the values to use when constructing the {@code ImmutableListMultimap} 1551 * @param keyFunction the function used to produce the key for each value 1552 * @return {@code ImmutableListMultimap} mapping the result of evaluating the function {@code 1553 * keyFunction} on each value in the input collection to that value 1554 * @throws NullPointerException if any element of {@code values} is {@code null}, or if {@code 1555 * keyFunction} produces {@code null} for any key 1556 * @since 10.0 1557 */ 1558 public static <K, V> ImmutableListMultimap<K, V> index( 1559 Iterator<V> values, Function<? super V, K> keyFunction) { 1560 checkNotNull(keyFunction); 1561 ImmutableListMultimap.Builder<K, V> builder = ImmutableListMultimap.builder(); 1562 while (values.hasNext()) { 1563 V value = values.next(); 1564 checkNotNull(value, values); 1565 builder.put(keyFunction.apply(value), value); 1566 } 1567 return builder.build(); 1568 } 1569 1570 static class Keys<K, V> extends AbstractMultiset<K> { 1571 @Weak final Multimap<K, V> multimap; 1572 1573 Keys(Multimap<K, V> multimap) { 1574 this.multimap = multimap; 1575 } 1576 1577 @Override 1578 Iterator<Multiset.Entry<K>> entryIterator() { 1579 return new TransformedIterator<Map.Entry<K, Collection<V>>, Multiset.Entry<K>>( 1580 multimap.asMap().entrySet().iterator()) { 1581 @Override 1582 Multiset.Entry<K> transform(final Map.Entry<K, Collection<V>> backingEntry) { 1583 return new Multisets.AbstractEntry<K>() { 1584 @Override 1585 public K getElement() { 1586 return backingEntry.getKey(); 1587 } 1588 1589 @Override 1590 public int getCount() { 1591 return backingEntry.getValue().size(); 1592 } 1593 }; 1594 } 1595 }; 1596 } 1597 1598 @Override 1599 int distinctElements() { 1600 return multimap.asMap().size(); 1601 } 1602 1603 @Override 1604 public int size() { 1605 return multimap.size(); 1606 } 1607 1608 @Override 1609 public boolean contains(@NullableDecl Object element) { 1610 return multimap.containsKey(element); 1611 } 1612 1613 @Override 1614 public Iterator<K> iterator() { 1615 return Maps.keyIterator(multimap.entries().iterator()); 1616 } 1617 1618 @Override 1619 public int count(@NullableDecl Object element) { 1620 Collection<V> values = Maps.safeGet(multimap.asMap(), element); 1621 return (values == null) ? 0 : values.size(); 1622 } 1623 1624 @Override 1625 public int remove(@NullableDecl Object element, int occurrences) { 1626 checkNonnegative(occurrences, "occurrences"); 1627 if (occurrences == 0) { 1628 return count(element); 1629 } 1630 1631 Collection<V> values = Maps.safeGet(multimap.asMap(), element); 1632 1633 if (values == null) { 1634 return 0; 1635 } 1636 1637 int oldCount = values.size(); 1638 if (occurrences >= oldCount) { 1639 values.clear(); 1640 } else { 1641 Iterator<V> iterator = values.iterator(); 1642 for (int i = 0; i < occurrences; i++) { 1643 iterator.next(); 1644 iterator.remove(); 1645 } 1646 } 1647 return oldCount; 1648 } 1649 1650 @Override 1651 public void clear() { 1652 multimap.clear(); 1653 } 1654 1655 @Override 1656 public Set<K> elementSet() { 1657 return multimap.keySet(); 1658 } 1659 1660 @Override 1661 Iterator<K> elementIterator() { 1662 throw new AssertionError("should never be called"); 1663 } 1664 } 1665 1666 /** A skeleton implementation of {@link Multimap#entries()}. */ 1667 abstract static class Entries<K, V> extends AbstractCollection<Map.Entry<K, V>> { 1668 abstract Multimap<K, V> multimap(); 1669 1670 @Override 1671 public int size() { 1672 return multimap().size(); 1673 } 1674 1675 @Override 1676 public boolean contains(@NullableDecl Object o) { 1677 if (o instanceof Map.Entry) { 1678 Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o; 1679 return multimap().containsEntry(entry.getKey(), entry.getValue()); 1680 } 1681 return false; 1682 } 1683 1684 @Override 1685 public boolean remove(@NullableDecl Object o) { 1686 if (o instanceof Map.Entry) { 1687 Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o; 1688 return multimap().remove(entry.getKey(), entry.getValue()); 1689 } 1690 return false; 1691 } 1692 1693 @Override 1694 public void clear() { 1695 multimap().clear(); 1696 } 1697 } 1698 1699 /** A skeleton implementation of {@link Multimap#asMap()}. */ 1700 static final class AsMap<K, V> extends Maps.ViewCachingAbstractMap<K, Collection<V>> { 1701 @Weak private final Multimap<K, V> multimap; 1702 1703 AsMap(Multimap<K, V> multimap) { 1704 this.multimap = checkNotNull(multimap); 1705 } 1706 1707 @Override 1708 public int size() { 1709 return multimap.keySet().size(); 1710 } 1711 1712 @Override 1713 protected Set<Entry<K, Collection<V>>> createEntrySet() { 1714 return new EntrySet(); 1715 } 1716 1717 void removeValuesForKey(Object key) { 1718 multimap.keySet().remove(key); 1719 } 1720 1721 @WeakOuter 1722 class EntrySet extends Maps.EntrySet<K, Collection<V>> { 1723 @Override 1724 Map<K, Collection<V>> map() { 1725 return AsMap.this; 1726 } 1727 1728 @Override 1729 public Iterator<Entry<K, Collection<V>>> iterator() { 1730 return Maps.asMapEntryIterator( 1731 multimap.keySet(), 1732 new Function<K, Collection<V>>() { 1733 @Override 1734 public Collection<V> apply(K key) { 1735 return multimap.get(key); 1736 } 1737 }); 1738 } 1739 1740 @Override 1741 public boolean remove(Object o) { 1742 if (!contains(o)) { 1743 return false; 1744 } 1745 Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o; 1746 removeValuesForKey(entry.getKey()); 1747 return true; 1748 } 1749 } 1750 1751 @SuppressWarnings("unchecked") 1752 @Override 1753 public Collection<V> get(Object key) { 1754 return containsKey(key) ? multimap.get((K) key) : null; 1755 } 1756 1757 @Override 1758 public Collection<V> remove(Object key) { 1759 return containsKey(key) ? multimap.removeAll(key) : null; 1760 } 1761 1762 @Override 1763 public Set<K> keySet() { 1764 return multimap.keySet(); 1765 } 1766 1767 @Override 1768 public boolean isEmpty() { 1769 return multimap.isEmpty(); 1770 } 1771 1772 @Override 1773 public boolean containsKey(Object key) { 1774 return multimap.containsKey(key); 1775 } 1776 1777 @Override 1778 public void clear() { 1779 multimap.clear(); 1780 } 1781 } 1782 1783 /** 1784 * Returns a multimap containing the mappings in {@code unfiltered} whose keys satisfy a 1785 * predicate. The returned multimap is a live view of {@code unfiltered}; changes to one affect 1786 * the other. 1787 * 1788 * <p>The resulting multimap's views have iterators that don't support {@code remove()}, but all 1789 * other methods are supported by the multimap and its views. When adding a key that doesn't 1790 * satisfy the predicate, the multimap's {@code put()}, {@code putAll()}, and {@code 1791 * replaceValues()} methods throw an {@link IllegalArgumentException}. 1792 * 1793 * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered 1794 * multimap or its views, only mappings whose keys satisfy the filter will be removed from the 1795 * underlying multimap. 1796 * 1797 * <p>The returned multimap isn't threadsafe or serializable, even if {@code unfiltered} is. 1798 * 1799 * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate across every 1800 * key/value mapping in the underlying multimap and determine which satisfy the filter. When a 1801 * live view is <i>not</i> needed, it may be faster to copy the filtered multimap and use the 1802 * copy. 1803 * 1804 * <p><b>Warning:</b> {@code keyPredicate} must be <i>consistent with equals</i>, as documented at 1805 * {@link Predicate#apply}. Do not provide a predicate such as {@code 1806 * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. 1807 * 1808 * @since 11.0 1809 */ 1810 public static <K, V> Multimap<K, V> filterKeys( 1811 Multimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) { 1812 if (unfiltered instanceof SetMultimap) { 1813 return filterKeys((SetMultimap<K, V>) unfiltered, keyPredicate); 1814 } else if (unfiltered instanceof ListMultimap) { 1815 return filterKeys((ListMultimap<K, V>) unfiltered, keyPredicate); 1816 } else if (unfiltered instanceof FilteredKeyMultimap) { 1817 FilteredKeyMultimap<K, V> prev = (FilteredKeyMultimap<K, V>) unfiltered; 1818 return new FilteredKeyMultimap<>( 1819 prev.unfiltered, Predicates.<K>and(prev.keyPredicate, keyPredicate)); 1820 } else if (unfiltered instanceof FilteredMultimap) { 1821 FilteredMultimap<K, V> prev = (FilteredMultimap<K, V>) unfiltered; 1822 return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate)); 1823 } else { 1824 return new FilteredKeyMultimap<>(unfiltered, keyPredicate); 1825 } 1826 } 1827 1828 /** 1829 * Returns a multimap containing the mappings in {@code unfiltered} whose keys satisfy a 1830 * predicate. The returned multimap is a live view of {@code unfiltered}; changes to one affect 1831 * the other. 1832 * 1833 * <p>The resulting multimap's views have iterators that don't support {@code remove()}, but all 1834 * other methods are supported by the multimap and its views. When adding a key that doesn't 1835 * satisfy the predicate, the multimap's {@code put()}, {@code putAll()}, and {@code 1836 * replaceValues()} methods throw an {@link IllegalArgumentException}. 1837 * 1838 * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered 1839 * multimap or its views, only mappings whose keys satisfy the filter will be removed from the 1840 * underlying multimap. 1841 * 1842 * <p>The returned multimap isn't threadsafe or serializable, even if {@code unfiltered} is. 1843 * 1844 * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate across every 1845 * key/value mapping in the underlying multimap and determine which satisfy the filter. When a 1846 * live view is <i>not</i> needed, it may be faster to copy the filtered multimap and use the 1847 * copy. 1848 * 1849 * <p><b>Warning:</b> {@code keyPredicate} must be <i>consistent with equals</i>, as documented at 1850 * {@link Predicate#apply}. Do not provide a predicate such as {@code 1851 * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. 1852 * 1853 * @since 14.0 1854 */ 1855 public static <K, V> SetMultimap<K, V> filterKeys( 1856 SetMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) { 1857 if (unfiltered instanceof FilteredKeySetMultimap) { 1858 FilteredKeySetMultimap<K, V> prev = (FilteredKeySetMultimap<K, V>) unfiltered; 1859 return new FilteredKeySetMultimap<>( 1860 prev.unfiltered(), Predicates.<K>and(prev.keyPredicate, keyPredicate)); 1861 } else if (unfiltered instanceof FilteredSetMultimap) { 1862 FilteredSetMultimap<K, V> prev = (FilteredSetMultimap<K, V>) unfiltered; 1863 return filterFiltered(prev, Maps.<K>keyPredicateOnEntries(keyPredicate)); 1864 } else { 1865 return new FilteredKeySetMultimap<>(unfiltered, keyPredicate); 1866 } 1867 } 1868 1869 /** 1870 * Returns a multimap containing the mappings in {@code unfiltered} whose keys satisfy a 1871 * predicate. The returned multimap is a live view of {@code unfiltered}; changes to one affect 1872 * the other. 1873 * 1874 * <p>The resulting multimap's views have iterators that don't support {@code remove()}, but all 1875 * other methods are supported by the multimap and its views. When adding a key that doesn't 1876 * satisfy the predicate, the multimap's {@code put()}, {@code putAll()}, and {@code 1877 * replaceValues()} methods throw an {@link IllegalArgumentException}. 1878 * 1879 * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered 1880 * multimap or its views, only mappings whose keys satisfy the filter will be removed from the 1881 * underlying multimap. 1882 * 1883 * <p>The returned multimap isn't threadsafe or serializable, even if {@code unfiltered} is. 1884 * 1885 * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate across every 1886 * key/value mapping in the underlying multimap and determine which satisfy the filter. When a 1887 * live view is <i>not</i> needed, it may be faster to copy the filtered multimap and use the 1888 * copy. 1889 * 1890 * <p><b>Warning:</b> {@code keyPredicate} must be <i>consistent with equals</i>, as documented at 1891 * {@link Predicate#apply}. Do not provide a predicate such as {@code 1892 * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. 1893 * 1894 * @since 14.0 1895 */ 1896 public static <K, V> ListMultimap<K, V> filterKeys( 1897 ListMultimap<K, V> unfiltered, final Predicate<? super K> keyPredicate) { 1898 if (unfiltered instanceof FilteredKeyListMultimap) { 1899 FilteredKeyListMultimap<K, V> prev = (FilteredKeyListMultimap<K, V>) unfiltered; 1900 return new FilteredKeyListMultimap<>( 1901 prev.unfiltered(), Predicates.<K>and(prev.keyPredicate, keyPredicate)); 1902 } else { 1903 return new FilteredKeyListMultimap<>(unfiltered, keyPredicate); 1904 } 1905 } 1906 1907 /** 1908 * Returns a multimap containing the mappings in {@code unfiltered} whose values satisfy a 1909 * predicate. The returned multimap is a live view of {@code unfiltered}; changes to one affect 1910 * the other. 1911 * 1912 * <p>The resulting multimap's views have iterators that don't support {@code remove()}, but all 1913 * other methods are supported by the multimap and its views. When adding a value that doesn't 1914 * satisfy the predicate, the multimap's {@code put()}, {@code putAll()}, and {@code 1915 * replaceValues()} methods throw an {@link IllegalArgumentException}. 1916 * 1917 * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered 1918 * multimap or its views, only mappings whose value satisfy the filter will be removed from the 1919 * underlying multimap. 1920 * 1921 * <p>The returned multimap isn't threadsafe or serializable, even if {@code unfiltered} is. 1922 * 1923 * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate across every 1924 * key/value mapping in the underlying multimap and determine which satisfy the filter. When a 1925 * live view is <i>not</i> needed, it may be faster to copy the filtered multimap and use the 1926 * copy. 1927 * 1928 * <p><b>Warning:</b> {@code valuePredicate} must be <i>consistent with equals</i>, as documented 1929 * at {@link Predicate#apply}. Do not provide a predicate such as {@code 1930 * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. 1931 * 1932 * @since 11.0 1933 */ 1934 public static <K, V> Multimap<K, V> filterValues( 1935 Multimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) { 1936 return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate)); 1937 } 1938 1939 /** 1940 * Returns a multimap containing the mappings in {@code unfiltered} whose values satisfy a 1941 * predicate. The returned multimap is a live view of {@code unfiltered}; changes to one affect 1942 * the other. 1943 * 1944 * <p>The resulting multimap's views have iterators that don't support {@code remove()}, but all 1945 * other methods are supported by the multimap and its views. When adding a value that doesn't 1946 * satisfy the predicate, the multimap's {@code put()}, {@code putAll()}, and {@code 1947 * replaceValues()} methods throw an {@link IllegalArgumentException}. 1948 * 1949 * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered 1950 * multimap or its views, only mappings whose value satisfy the filter will be removed from the 1951 * underlying multimap. 1952 * 1953 * <p>The returned multimap isn't threadsafe or serializable, even if {@code unfiltered} is. 1954 * 1955 * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate across every 1956 * key/value mapping in the underlying multimap and determine which satisfy the filter. When a 1957 * live view is <i>not</i> needed, it may be faster to copy the filtered multimap and use the 1958 * copy. 1959 * 1960 * <p><b>Warning:</b> {@code valuePredicate} must be <i>consistent with equals</i>, as documented 1961 * at {@link Predicate#apply}. Do not provide a predicate such as {@code 1962 * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. 1963 * 1964 * @since 14.0 1965 */ 1966 public static <K, V> SetMultimap<K, V> filterValues( 1967 SetMultimap<K, V> unfiltered, final Predicate<? super V> valuePredicate) { 1968 return filterEntries(unfiltered, Maps.<V>valuePredicateOnEntries(valuePredicate)); 1969 } 1970 1971 /** 1972 * Returns a multimap containing the mappings in {@code unfiltered} that satisfy a predicate. The 1973 * returned multimap is a live view of {@code unfiltered}; changes to one affect the other. 1974 * 1975 * <p>The resulting multimap's views have iterators that don't support {@code remove()}, but all 1976 * other methods are supported by the multimap and its views. When adding a key/value pair that 1977 * doesn't satisfy the predicate, multimap's {@code put()}, {@code putAll()}, and {@code 1978 * replaceValues()} methods throw an {@link IllegalArgumentException}. 1979 * 1980 * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered 1981 * multimap or its views, only mappings whose keys satisfy the filter will be removed from the 1982 * underlying multimap. 1983 * 1984 * <p>The returned multimap isn't threadsafe or serializable, even if {@code unfiltered} is. 1985 * 1986 * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate across every 1987 * key/value mapping in the underlying multimap and determine which satisfy the filter. When a 1988 * live view is <i>not</i> needed, it may be faster to copy the filtered multimap and use the 1989 * copy. 1990 * 1991 * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with equals</i>, as documented 1992 * at {@link Predicate#apply}. 1993 * 1994 * @since 11.0 1995 */ 1996 public static <K, V> Multimap<K, V> filterEntries( 1997 Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) { 1998 checkNotNull(entryPredicate); 1999 if (unfiltered instanceof SetMultimap) { 2000 return filterEntries((SetMultimap<K, V>) unfiltered, entryPredicate); 2001 } 2002 return (unfiltered instanceof FilteredMultimap) 2003 ? filterFiltered((FilteredMultimap<K, V>) unfiltered, entryPredicate) 2004 : new FilteredEntryMultimap<K, V>(checkNotNull(unfiltered), entryPredicate); 2005 } 2006 2007 /** 2008 * Returns a multimap containing the mappings in {@code unfiltered} that satisfy a predicate. The 2009 * returned multimap is a live view of {@code unfiltered}; changes to one affect the other. 2010 * 2011 * <p>The resulting multimap's views have iterators that don't support {@code remove()}, but all 2012 * other methods are supported by the multimap and its views. When adding a key/value pair that 2013 * doesn't satisfy the predicate, multimap's {@code put()}, {@code putAll()}, and {@code 2014 * replaceValues()} methods throw an {@link IllegalArgumentException}. 2015 * 2016 * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered 2017 * multimap or its views, only mappings whose keys satisfy the filter will be removed from the 2018 * underlying multimap. 2019 * 2020 * <p>The returned multimap isn't threadsafe or serializable, even if {@code unfiltered} is. 2021 * 2022 * <p>Many of the filtered multimap's methods, such as {@code size()}, iterate across every 2023 * key/value mapping in the underlying multimap and determine which satisfy the filter. When a 2024 * live view is <i>not</i> needed, it may be faster to copy the filtered multimap and use the 2025 * copy. 2026 * 2027 * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with equals</i>, as documented 2028 * at {@link Predicate#apply}. 2029 * 2030 * @since 14.0 2031 */ 2032 public static <K, V> SetMultimap<K, V> filterEntries( 2033 SetMultimap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) { 2034 checkNotNull(entryPredicate); 2035 return (unfiltered instanceof FilteredSetMultimap) 2036 ? filterFiltered((FilteredSetMultimap<K, V>) unfiltered, entryPredicate) 2037 : new FilteredEntrySetMultimap<K, V>(checkNotNull(unfiltered), entryPredicate); 2038 } 2039 2040 /** 2041 * Support removal operations when filtering a filtered multimap. Since a filtered multimap has 2042 * iterators that don't support remove, passing one to the FilteredEntryMultimap constructor would 2043 * lead to a multimap whose removal operations would fail. This method combines the predicates to 2044 * avoid that problem. 2045 */ 2046 private static <K, V> Multimap<K, V> filterFiltered( 2047 FilteredMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) { 2048 Predicate<Entry<K, V>> predicate = 2049 Predicates.<Entry<K, V>>and(multimap.entryPredicate(), entryPredicate); 2050 return new FilteredEntryMultimap<>(multimap.unfiltered(), predicate); 2051 } 2052 2053 /** 2054 * Support removal operations when filtering a filtered multimap. Since a filtered multimap has 2055 * iterators that don't support remove, passing one to the FilteredEntryMultimap constructor would 2056 * lead to a multimap whose removal operations would fail. This method combines the predicates to 2057 * avoid that problem. 2058 */ 2059 private static <K, V> SetMultimap<K, V> filterFiltered( 2060 FilteredSetMultimap<K, V> multimap, Predicate<? super Entry<K, V>> entryPredicate) { 2061 Predicate<Entry<K, V>> predicate = 2062 Predicates.<Entry<K, V>>and(multimap.entryPredicate(), entryPredicate); 2063 return new FilteredEntrySetMultimap<>(multimap.unfiltered(), predicate); 2064 } 2065 2066 static boolean equalsImpl(Multimap<?, ?> multimap, @NullableDecl Object object) { 2067 if (object == multimap) { 2068 return true; 2069 } 2070 if (object instanceof Multimap) { 2071 Multimap<?, ?> that = (Multimap<?, ?>) object; 2072 return multimap.asMap().equals(that.asMap()); 2073 } 2074 return false; 2075 } 2076 2077 // TODO(jlevy): Create methods that filter a SortedSetMultimap. 2078 } 2079