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