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