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