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