1 /* 2 * Copyright (C) 2007 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import com.google.common.annotations.GwtCompatible; 20 import com.google.common.base.Function; 21 import com.google.common.base.Joiner; 22 import com.google.common.base.Joiner.MapJoiner; 23 import com.google.common.base.Preconditions; 24 import static com.google.common.base.Preconditions.checkNotNull; 25 import static com.google.common.base.Preconditions.checkState; 26 import com.google.common.base.Supplier; 27 28 import java.io.IOException; 29 import java.io.ObjectInputStream; 30 import java.io.ObjectOutputStream; 31 import java.io.Serializable; 32 import java.util.AbstractSet; 33 import java.util.Collection; 34 import java.util.Collections; 35 import java.util.Comparator; 36 import java.util.HashSet; 37 import java.util.Iterator; 38 import java.util.List; 39 import java.util.Map; 40 import java.util.Map.Entry; 41 import java.util.NoSuchElementException; 42 import java.util.Set; 43 import java.util.SortedSet; 44 45 import javax.annotation.Nullable; 46 47 /** 48 * Provides static methods acting on or generating a {@code Multimap}. 49 * 50 * @author Jared Levy 51 * @author Robert Konigsberg 52 * @author Mike Bostock 53 * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library) 54 */ 55 @GwtCompatible 56 public final class Multimaps { 57 private Multimaps() {} 58 59 /** 60 * Creates a new {@code Multimap} that uses the provided map and factory. It 61 * can generate a multimap based on arbitrary {@link Map} and 62 * {@link Collection} classes. 63 * 64 * <p>The {@code factory}-generated and {@code map} classes determine the 65 * multimap iteration order. They also specify the behavior of the 66 * {@code equals}, {@code hashCode}, and {@code toString} methods for the 67 * multimap and its returned views. However, the multimap's {@code get} 68 * method returns instances of a different class than {@code factory.get()} 69 * does. 70 * 71 * <p>The multimap is serializable if {@code map}, {@code factory}, the 72 * collections generated by {@code factory}, and the multimap contents are all 73 * serializable. 74 * 75 * <p>The multimap is not threadsafe when any concurrent operations update the 76 * multimap, even if {@code map} and the instances generated by 77 * {@code factory} are. Concurrent read operations will work correctly. To 78 * allow concurrent update operations, wrap the multimap with a call to 79 * {@link #synchronizedMultimap}. 80 * 81 * <p>Call this method only when the simpler methods 82 * {@link ArrayListMultimap#create()}, {@link HashMultimap#create()}, 83 * {@link LinkedHashMultimap#create()}, {@link LinkedListMultimap#create()}, 84 * {@link TreeMultimap#create()}, and 85 * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice. 86 * 87 * <p>Note: the multimap assumes complete ownership over of {@code map} and 88 * the collections returned by {@code factory}. Those objects should not be 89 * manually updated and they should not use soft, weak, or phantom references. 90 * 91 * @param map place to store the mapping from each key to its corresponding 92 * values 93 * @param factory supplier of new, empty collections that will each hold all 94 * values for a given key 95 * @throws IllegalArgumentException if {@code map} is not empty 96 */ 97 public static <K, V> Multimap<K, V> newMultimap(Map<K, Collection<V>> map, 98 final Supplier<? extends Collection<V>> factory) { 99 return new CustomMultimap<K, V>(map, factory); 100 } 101 102 private static class CustomMultimap<K, V> extends AbstractMultimap<K, V> { 103 transient Supplier<? extends Collection<V>> factory; 104 105 CustomMultimap(Map<K, Collection<V>> map, 106 Supplier<? extends Collection<V>> factory) { 107 super(map); 108 this.factory = checkNotNull(factory); 109 } 110 111 @Override protected Collection<V> createCollection() { 112 return factory.get(); 113 } 114 115 // can't use Serialization writeMultimap and populateMultimap methods since 116 // there's no way to generate the empty backing map. 117 118 /** @serialData the factory and the backing map */ 119 private void writeObject(ObjectOutputStream stream) throws IOException { 120 stream.defaultWriteObject(); 121 stream.writeObject(factory); 122 stream.writeObject(backingMap()); 123 } 124 125 @SuppressWarnings("unchecked") // reading data stored by writeObject 126 private void readObject(ObjectInputStream stream) 127 throws IOException, ClassNotFoundException { 128 stream.defaultReadObject(); 129 factory = (Supplier<? extends Collection<V>>) stream.readObject(); 130 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); 131 setMap(map); 132 } 133 134 private static final long serialVersionUID = 0; 135 } 136 137 /** 138 * Creates a new {@code ListMultimap} that uses the provided map and factory. 139 * It can generate a multimap based on arbitrary {@link Map} and {@link List} 140 * classes. 141 * 142 * <p>The {@code factory}-generated and {@code map} classes determine the 143 * multimap iteration order. They also specify the behavior of the 144 * {@code equals}, {@code hashCode}, and {@code toString} methods for the 145 * multimap and its returned views. The multimap's {@code get}, {@code 146 * removeAll}, and {@code replaceValues} methods return {@code RandomAccess} 147 * lists if the factory does. However, the multimap's {@code get} method 148 * returns instances of a different class than does {@code factory.get()}. 149 * 150 * <p>The multimap is serializable if {@code map}, {@code factory}, the 151 * lists generated by {@code factory}, and the multimap contents are all 152 * serializable. 153 * 154 * <p>The multimap is not threadsafe when any concurrent operations update the 155 * multimap, even if {@code map} and the instances generated by 156 * {@code factory} are. Concurrent read operations will work correctly. To 157 * allow concurrent update operations, wrap the multimap with a call to 158 * {@link #synchronizedListMultimap}. 159 * 160 * <p>Call this method only when the simpler methods 161 * {@link ArrayListMultimap#create()} and {@link LinkedListMultimap#create()} 162 * won't suffice. 163 * 164 * <p>Note: the multimap assumes complete ownership over of {@code map} and 165 * the lists returned by {@code factory}. Those objects should not be manually 166 * updated and they should not use soft, weak, or phantom references. 167 * 168 * @param map place to store the mapping from each key to its corresponding 169 * values 170 * @param factory supplier of new, empty lists that will each hold all values 171 * for a given key 172 * @throws IllegalArgumentException if {@code map} is not empty 173 */ 174 public static <K, V> ListMultimap<K, V> newListMultimap( 175 Map<K, Collection<V>> map, final Supplier<? extends List<V>> factory) { 176 return new CustomListMultimap<K, V>(map, factory); 177 } 178 179 private static class CustomListMultimap<K, V> 180 extends AbstractListMultimap<K, V> { 181 transient Supplier<? extends List<V>> factory; 182 183 CustomListMultimap(Map<K, Collection<V>> map, 184 Supplier<? extends List<V>> factory) { 185 super(map); 186 this.factory = checkNotNull(factory); 187 } 188 189 @Override protected List<V> createCollection() { 190 return factory.get(); 191 } 192 193 /** @serialData the factory and the backing map */ 194 private void writeObject(ObjectOutputStream stream) throws IOException { 195 stream.defaultWriteObject(); 196 stream.writeObject(factory); 197 stream.writeObject(backingMap()); 198 } 199 200 @SuppressWarnings("unchecked") // reading data stored by writeObject 201 private void readObject(ObjectInputStream stream) 202 throws IOException, ClassNotFoundException { 203 stream.defaultReadObject(); 204 factory = (Supplier<? extends List<V>>) stream.readObject(); 205 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); 206 setMap(map); 207 } 208 209 private static final long serialVersionUID = 0; 210 } 211 212 /** 213 * Creates a new {@code SetMultimap} that uses the provided map and factory. 214 * It can generate a multimap based on arbitrary {@link Map} and {@link Set} 215 * classes. 216 * 217 * <p>The {@code factory}-generated and {@code map} classes determine the 218 * multimap iteration order. They also specify the behavior of the 219 * {@code equals}, {@code hashCode}, and {@code toString} methods for the 220 * multimap and its returned views. However, the multimap's {@code get} 221 * method returns instances of a different class than {@code factory.get()} 222 * does. 223 * 224 * <p>The multimap is serializable if {@code map}, {@code factory}, the 225 * sets generated by {@code factory}, and the multimap contents are all 226 * serializable. 227 * 228 * <p>The multimap is not threadsafe when any concurrent operations update the 229 * multimap, even if {@code map} and the instances generated by 230 * {@code factory} are. Concurrent read operations will work correctly. To 231 * allow concurrent update operations, wrap the multimap with a call to 232 * {@link #synchronizedSetMultimap}. 233 * 234 * <p>Call this method only when the simpler methods 235 * {@link HashMultimap#create()}, {@link LinkedHashMultimap#create()}, 236 * {@link TreeMultimap#create()}, and 237 * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice. 238 * 239 * <p>Note: the multimap assumes complete ownership over of {@code map} and 240 * the sets returned by {@code factory}. Those objects should not be manually 241 * updated and they should not use soft, weak, or phantom references. 242 * 243 * @param map place to store the mapping from each key to its corresponding 244 * values 245 * @param factory supplier of new, empty sets that will each hold all values 246 * for a given key 247 * @throws IllegalArgumentException if {@code map} is not empty 248 */ 249 public static <K, V> SetMultimap<K, V> newSetMultimap( 250 Map<K, Collection<V>> map, final Supplier<? extends Set<V>> factory) { 251 return new CustomSetMultimap<K, V>(map, factory); 252 } 253 254 private static class CustomSetMultimap<K, V> 255 extends AbstractSetMultimap<K, V> { 256 transient Supplier<? extends Set<V>> factory; 257 258 CustomSetMultimap(Map<K, Collection<V>> map, 259 Supplier<? extends Set<V>> factory) { 260 super(map); 261 this.factory = checkNotNull(factory); 262 } 263 264 @Override protected Set<V> createCollection() { 265 return factory.get(); 266 } 267 268 /** @serialData the factory and the backing map */ 269 private void writeObject(ObjectOutputStream stream) throws IOException { 270 stream.defaultWriteObject(); 271 stream.writeObject(factory); 272 stream.writeObject(backingMap()); 273 } 274 275 @SuppressWarnings("unchecked") // reading data stored by writeObject 276 private void readObject(ObjectInputStream stream) 277 throws IOException, ClassNotFoundException { 278 stream.defaultReadObject(); 279 factory = (Supplier<? extends Set<V>>) stream.readObject(); 280 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); 281 setMap(map); 282 } 283 284 private static final long serialVersionUID = 0; 285 } 286 287 /** 288 * Creates a new {@code SortedSetMultimap} that uses the provided map and 289 * factory. It can generate a multimap based on arbitrary {@link Map} and 290 * {@link SortedSet} classes. 291 * 292 * <p>The {@code factory}-generated and {@code map} classes determine the 293 * multimap iteration order. They also specify the behavior of the 294 * {@code equals}, {@code hashCode}, and {@code toString} methods for the 295 * multimap and its returned views. However, the multimap's {@code get} 296 * method returns instances of a different class than {@code factory.get()} 297 * does. 298 * 299 * <p>The multimap is serializable if {@code map}, {@code factory}, the 300 * sets generated by {@code factory}, and the multimap contents are all 301 * serializable. 302 * 303 * <p>The multimap is not threadsafe when any concurrent operations update the 304 * multimap, even if {@code map} and the instances generated by 305 * {@code factory} are. Concurrent read operations will work correctly. To 306 * allow concurrent update operations, wrap the multimap with a call to 307 * {@link #synchronizedSortedSetMultimap}. 308 * 309 * <p>Call this method only when the simpler methods 310 * {@link TreeMultimap#create()} and 311 * {@link TreeMultimap#create(Comparator, Comparator)} won't suffice. 312 * 313 * <p>Note: the multimap assumes complete ownership over of {@code map} and 314 * the sets returned by {@code factory}. Those objects should not be manually 315 * updated and they should not use soft, weak, or phantom references. 316 * 317 * @param map place to store the mapping from each key to its corresponding 318 * values 319 * @param factory supplier of new, empty sorted sets that will each hold 320 * all values for a given key 321 * @throws IllegalArgumentException if {@code map} is not empty 322 */ 323 public static <K, V> SortedSetMultimap<K, V> newSortedSetMultimap( 324 Map<K, Collection<V>> map, 325 final Supplier<? extends SortedSet<V>> factory) { 326 return new CustomSortedSetMultimap<K, V>(map, factory); 327 } 328 329 private static class CustomSortedSetMultimap<K, V> 330 extends AbstractSortedSetMultimap<K, V> { 331 transient Supplier<? extends SortedSet<V>> factory; 332 transient Comparator<? super V> valueComparator; 333 334 CustomSortedSetMultimap(Map<K, Collection<V>> map, 335 Supplier<? extends SortedSet<V>> factory) { 336 super(map); 337 this.factory = checkNotNull(factory); 338 valueComparator = factory.get().comparator(); 339 } 340 341 @Override protected SortedSet<V> createCollection() { 342 return factory.get(); 343 } 344 345 /*@Override*/ public Comparator<? super V> valueComparator() { 346 return valueComparator; 347 } 348 349 /** @serialData the factory and the backing map */ 350 private void writeObject(ObjectOutputStream stream) throws IOException { 351 stream.defaultWriteObject(); 352 stream.writeObject(factory); 353 stream.writeObject(backingMap()); 354 } 355 356 @SuppressWarnings("unchecked") // reading data stored by writeObject 357 private void readObject(ObjectInputStream stream) 358 throws IOException, ClassNotFoundException { 359 stream.defaultReadObject(); 360 factory = (Supplier<? extends SortedSet<V>>) stream.readObject(); 361 valueComparator = factory.get().comparator(); 362 Map<K, Collection<V>> map = (Map<K, Collection<V>>) stream.readObject(); 363 setMap(map); 364 } 365 366 private static final long serialVersionUID = 0; 367 } 368 369 /** 370 * Copies each key-value mapping in {@code source} into {@code dest}, with 371 * its key and value reversed. 372 * 373 * @param source any multimap 374 * @param dest the multimap to copy into; usually empty 375 * @return {@code dest} 376 */ 377 public static <K, V, M extends Multimap<K, V>> M invertFrom( 378 Multimap<? extends V, ? extends K> source, M dest) { 379 for (Map.Entry<? extends V, ? extends K> entry : source.entries()) { 380 dest.put(entry.getValue(), entry.getKey()); 381 } 382 return dest; 383 } 384 385 /** 386 * Returns a synchronized (thread-safe) multimap backed by the specified 387 * multimap. In order to guarantee serial access, it is critical that 388 * <b>all</b> access to the backing multimap is accomplished through the 389 * returned multimap. 390 * 391 * <p>It is imperative that the user manually synchronize on the returned 392 * multimap when accessing any of its collection views: <pre> {@code 393 * 394 * Multimap<K, V> m = Multimaps.synchronizedMultimap( 395 * HashMultimap.<K, V>create()); 396 * ... 397 * Set<K> s = m.keySet(); // Needn't be in synchronized block 398 * ... 399 * synchronized (m) { // Synchronizing on m, not s! 400 * Iterator<K> i = s.iterator(); // Must be in synchronized block 401 * while (i.hasNext()) { 402 * foo(i.next()); 403 * } 404 * }}</pre> 405 * 406 * Failure to follow this advice may result in non-deterministic behavior. 407 * 408 * <p>Note that the generated multimap's {@link Multimap#removeAll} and 409 * {@link Multimap#replaceValues} methods return collections that aren't 410 * synchronized. 411 * 412 * <p>The returned multimap will be serializable if the specified multimap is 413 * serializable. 414 * 415 * @param multimap the multimap to be wrapped in a synchronized view 416 * @return a synchronized view of the specified multimap 417 */ 418 public static <K, V> Multimap<K, V> synchronizedMultimap( 419 Multimap<K, V> multimap) { 420 return Synchronized.multimap(multimap, null); 421 } 422 423 /** 424 * Returns an unmodifiable view of the specified multimap. Query operations on 425 * the returned multimap "read through" to the specified multimap, and 426 * attempts to modify the returned multimap, either directly or through the 427 * multimap's views, result in an {@code UnsupportedOperationException}. 428 * 429 * <p>Note that the generated multimap's {@link Multimap#removeAll} and 430 * {@link Multimap#replaceValues} methods return collections that are 431 * modifiable. 432 * 433 * <p>The returned multimap will be serializable if the specified multimap is 434 * serializable. 435 * 436 * @param delegate the multimap for which an unmodifiable view is to be 437 * returned 438 * @return an unmodifiable view of the specified multimap 439 */ 440 public static <K, V> Multimap<K, V> unmodifiableMultimap( 441 Multimap<K, V> delegate) { 442 return new UnmodifiableMultimap<K, V>(delegate); 443 } 444 445 private static class UnmodifiableMultimap<K, V> 446 extends ForwardingMultimap<K, V> implements Serializable { 447 final Multimap<K, V> delegate; 448 transient Collection<Entry<K, V>> entries; 449 transient Multiset<K> keys; 450 transient Set<K> keySet; 451 transient Collection<V> values; 452 transient Map<K, Collection<V>> map; 453 454 UnmodifiableMultimap(final Multimap<K, V> delegate) { 455 this.delegate = delegate; 456 } 457 458 @Override protected Multimap<K, V> delegate() { 459 return delegate; 460 } 461 462 @Override public void clear() { 463 throw new UnsupportedOperationException(); 464 } 465 466 @Override public Map<K, Collection<V>> asMap() { 467 Map<K, Collection<V>> result = map; 468 if (result == null) { 469 final Map<K, Collection<V>> unmodifiableMap 470 = Collections.unmodifiableMap(delegate.asMap()); 471 map = result = new ForwardingMap<K, Collection<V>>() { 472 @Override protected Map<K, Collection<V>> delegate() { 473 return unmodifiableMap; 474 } 475 476 Set<Entry<K, Collection<V>>> entrySet; 477 478 @Override public Set<Map.Entry<K, Collection<V>>> entrySet() { 479 Set<Entry<K, Collection<V>>> result = entrySet; 480 return (result == null) 481 ? entrySet 482 = unmodifiableAsMapEntries(unmodifiableMap.entrySet()) 483 : result; 484 } 485 486 @Override public Collection<V> get(Object key) { 487 Collection<V> collection = unmodifiableMap.get(key); 488 return (collection == null) 489 ? null : unmodifiableValueCollection(collection); 490 } 491 492 Collection<Collection<V>> asMapValues; 493 494 @Override public Collection<Collection<V>> values() { 495 Collection<Collection<V>> result = asMapValues; 496 return (result == null) 497 ? asMapValues 498 = new UnmodifiableAsMapValues<V>(unmodifiableMap.values()) 499 : result; 500 } 501 502 @Override public boolean containsValue(Object o) { 503 return values().contains(o); 504 } 505 }; 506 } 507 return result; 508 } 509 510 @Override public Collection<Entry<K, V>> entries() { 511 Collection<Entry<K, V>> result = entries; 512 if (result == null) { 513 entries = result = unmodifiableEntries(delegate.entries()); 514 } 515 return result; 516 } 517 518 @Override public Collection<V> get(K key) { 519 return unmodifiableValueCollection(delegate.get(key)); 520 } 521 522 @Override public Multiset<K> keys() { 523 Multiset<K> result = keys; 524 if (result == null) { 525 keys = result = Multisets.unmodifiableMultiset(delegate.keys()); 526 } 527 return result; 528 } 529 530 @Override public Set<K> keySet() { 531 Set<K> result = keySet; 532 if (result == null) { 533 keySet = result = Collections.unmodifiableSet(delegate.keySet()); 534 } 535 return result; 536 } 537 538 @Override public boolean put(K key, V value) { 539 throw new UnsupportedOperationException(); 540 } 541 542 @Override public boolean putAll(K key, 543 @SuppressWarnings("hiding") Iterable<? extends V> values) { 544 throw new UnsupportedOperationException(); 545 } 546 547 @Override 548 public boolean putAll(Multimap<? extends K, ? extends V> multimap) { 549 throw new UnsupportedOperationException(); 550 } 551 552 @Override public boolean remove(Object key, Object value) { 553 throw new UnsupportedOperationException(); 554 } 555 556 @Override public Collection<V> removeAll(Object key) { 557 throw new UnsupportedOperationException(); 558 } 559 560 @Override public Collection<V> replaceValues(K key, 561 @SuppressWarnings("hiding") Iterable<? extends V> values) { 562 throw new UnsupportedOperationException(); 563 } 564 565 @Override public Collection<V> values() { 566 Collection<V> result = values; 567 if (result == null) { 568 values = result = Collections.unmodifiableCollection(delegate.values()); 569 } 570 return result; 571 } 572 573 private static final long serialVersionUID = 0; 574 } 575 576 private static class UnmodifiableAsMapValues<V> 577 extends ForwardingCollection<Collection<V>> { 578 final Collection<Collection<V>> delegate; 579 UnmodifiableAsMapValues(Collection<Collection<V>> delegate) { 580 this.delegate = Collections.unmodifiableCollection(delegate); 581 } 582 @Override protected Collection<Collection<V>> delegate() { 583 return delegate; 584 } 585 @Override public Iterator<Collection<V>> iterator() { 586 final Iterator<Collection<V>> iterator = delegate.iterator(); 587 return new Iterator<Collection<V>>() { 588 public boolean hasNext() { 589 return iterator.hasNext(); 590 } 591 public Collection<V> next() { 592 return unmodifiableValueCollection(iterator.next()); 593 } 594 public void remove() { 595 throw new UnsupportedOperationException(); 596 } 597 }; 598 } 599 @Override public Object[] toArray() { 600 return ObjectArrays.toArrayImpl(this); 601 } 602 @Override public <T> T[] toArray(T[] array) { 603 return ObjectArrays.toArrayImpl(this, array); 604 } 605 @Override public boolean contains(Object o) { 606 return Iterators.contains(iterator(), o); 607 } 608 @Override public boolean containsAll(Collection<?> c) { 609 return Collections2.containsAll(this, c); 610 } 611 } 612 613 private static class UnmodifiableListMultimap<K, V> 614 extends UnmodifiableMultimap<K, V> implements ListMultimap<K, V> { 615 UnmodifiableListMultimap(ListMultimap<K, V> delegate) { 616 super(delegate); 617 } 618 @Override public ListMultimap<K, V> delegate() { 619 return (ListMultimap<K, V>) super.delegate(); 620 } 621 @Override public List<V> get(K key) { 622 return Collections.unmodifiableList(delegate().get(key)); 623 } 624 @Override public List<V> removeAll(Object key) { 625 throw new UnsupportedOperationException(); 626 } 627 @Override public List<V> replaceValues( 628 K key, @SuppressWarnings("hiding") Iterable<? extends V> values) { 629 throw new UnsupportedOperationException(); 630 } 631 private static final long serialVersionUID = 0; 632 } 633 634 private static class UnmodifiableSetMultimap<K, V> 635 extends UnmodifiableMultimap<K, V> implements SetMultimap<K, V> { 636 UnmodifiableSetMultimap(SetMultimap<K, V> delegate) { 637 super(delegate); 638 } 639 @Override public SetMultimap<K, V> delegate() { 640 return (SetMultimap<K, V>) super.delegate(); 641 } 642 @Override public Set<V> get(K key) { 643 /* 644 * Note that this doesn't return a SortedSet when delegate is a 645 * SortedSetMultiset, unlike (SortedSet<V>) super.get(). 646 */ 647 return Collections.unmodifiableSet(delegate().get(key)); 648 } 649 @Override public Set<Map.Entry<K, V>> entries() { 650 return Maps.unmodifiableEntrySet(delegate().entries()); 651 } 652 @Override public Set<V> removeAll(Object key) { 653 throw new UnsupportedOperationException(); 654 } 655 @Override public Set<V> replaceValues( 656 K key, @SuppressWarnings("hiding") Iterable<? extends V> values) { 657 throw new UnsupportedOperationException(); 658 } 659 private static final long serialVersionUID = 0; 660 } 661 662 private static class UnmodifiableSortedSetMultimap<K, V> 663 extends UnmodifiableSetMultimap<K, V> implements SortedSetMultimap<K, V> { 664 UnmodifiableSortedSetMultimap(SortedSetMultimap<K, V> delegate) { 665 super(delegate); 666 } 667 @Override public SortedSetMultimap<K, V> delegate() { 668 return (SortedSetMultimap<K, V>) super.delegate(); 669 } 670 @Override public SortedSet<V> get(K key) { 671 return Collections.unmodifiableSortedSet(delegate().get(key)); 672 } 673 @Override public SortedSet<V> removeAll(Object key) { 674 throw new UnsupportedOperationException(); 675 } 676 @Override public SortedSet<V> replaceValues( 677 K key, @SuppressWarnings("hiding") Iterable<? extends V> values) { 678 throw new UnsupportedOperationException(); 679 } 680 public Comparator<? super V> valueComparator() { 681 return delegate().valueComparator(); 682 } 683 private static final long serialVersionUID = 0; 684 } 685 686 /** 687 * Returns a synchronized (thread-safe) {@code SetMultimap} backed by the 688 * specified multimap. 689 * 690 * <p>You must follow the warnings described in {@link #synchronizedMultimap}. 691 * 692 * <p>The returned multimap will be serializable if the specified multimap is 693 * serializable. 694 * 695 * @param multimap the multimap to be wrapped 696 * @return a synchronized view of the specified multimap 697 */ 698 public static <K, V> SetMultimap<K, V> synchronizedSetMultimap( 699 SetMultimap<K, V> multimap) { 700 return Synchronized.setMultimap(multimap, null); 701 } 702 703 /** 704 * Returns an unmodifiable view of the specified {@code SetMultimap}. Query 705 * operations on the returned multimap "read through" to the specified 706 * multimap, and attempts to modify the returned multimap, either directly or 707 * through the multimap's views, result in an 708 * {@code UnsupportedOperationException}. 709 * 710 * <p>Note that the generated multimap's {@link Multimap#removeAll} and 711 * {@link Multimap#replaceValues} methods return collections that are 712 * modifiable. 713 * 714 * <p>The returned multimap will be serializable if the specified multimap is 715 * serializable. 716 * 717 * @param delegate the multimap for which an unmodifiable view is to be 718 * returned 719 * @return an unmodifiable view of the specified multimap 720 */ 721 public static <K, V> SetMultimap<K, V> unmodifiableSetMultimap( 722 SetMultimap<K, V> delegate) { 723 return new UnmodifiableSetMultimap<K, V>(delegate); 724 } 725 726 /** 727 * Returns a synchronized (thread-safe) {@code SortedSetMultimap} backed by 728 * the specified multimap. 729 * 730 * <p>You must follow the warnings described in {@link #synchronizedMultimap}. 731 * 732 * <p>The returned multimap will be serializable if the specified multimap is 733 * serializable. 734 * 735 * @param multimap the multimap to be wrapped 736 * @return a synchronized view of the specified multimap 737 */ 738 public static <K, V> SortedSetMultimap<K, V> 739 synchronizedSortedSetMultimap(SortedSetMultimap<K, V> multimap) { 740 return Synchronized.sortedSetMultimap(multimap, null); 741 } 742 743 /** 744 * Returns an unmodifiable view of the specified {@code SortedSetMultimap}. 745 * Query operations on the returned multimap "read through" to the specified 746 * multimap, and attempts to modify the returned multimap, either directly or 747 * through the multimap's views, result in an 748 * {@code UnsupportedOperationException}. 749 * 750 * <p>Note that the generated multimap's {@link Multimap#removeAll} and 751 * {@link Multimap#replaceValues} methods return collections that are 752 * modifiable. 753 * 754 * <p>The returned multimap will be serializable if the specified multimap is 755 * serializable. 756 * 757 * @param delegate the multimap for which an unmodifiable view is to be 758 * returned 759 * @return an unmodifiable view of the specified multimap 760 */ 761 public static <K, V> SortedSetMultimap<K, V> unmodifiableSortedSetMultimap( 762 SortedSetMultimap<K, V> delegate) { 763 return new UnmodifiableSortedSetMultimap<K, V>(delegate); 764 } 765 766 /** 767 * Returns a synchronized (thread-safe) {@code ListMultimap} backed by the 768 * specified multimap. 769 * 770 * <p>You must follow the warnings described in {@link #synchronizedMultimap}. 771 * 772 * @param multimap the multimap to be wrapped 773 * @return a synchronized view of the specified multimap 774 */ 775 public static <K, V> ListMultimap<K, V> synchronizedListMultimap( 776 ListMultimap<K, V> multimap) { 777 return Synchronized.listMultimap(multimap, null); 778 } 779 780 /** 781 * Returns an unmodifiable view of the specified {@code ListMultimap}. Query 782 * operations on the returned multimap "read through" to the specified 783 * multimap, and attempts to modify the returned multimap, either directly or 784 * through the multimap's views, result in an 785 * {@code UnsupportedOperationException}. 786 * 787 * <p>Note that the generated multimap's {@link Multimap#removeAll} and 788 * {@link Multimap#replaceValues} methods return collections that are 789 * modifiable. 790 * 791 * <p>The returned multimap will be serializable if the specified multimap is 792 * serializable. 793 * 794 * @param delegate the multimap for which an unmodifiable view is to be 795 * returned 796 * @return an unmodifiable view of the specified multimap 797 */ 798 public static <K, V> ListMultimap<K, V> unmodifiableListMultimap( 799 ListMultimap<K, V> delegate) { 800 return new UnmodifiableListMultimap<K, V>(delegate); 801 } 802 803 /** 804 * Returns an unmodifiable view of the specified collection, preserving the 805 * interface for instances of {@code SortedSet}, {@code Set}, {@code List} and 806 * {@code Collection}, in that order of preference. 807 * 808 * @param collection the collection for which to return an unmodifiable view 809 * @return an unmodifiable view of the collection 810 */ 811 private static <V> Collection<V> unmodifiableValueCollection( 812 Collection<V> collection) { 813 if (collection instanceof SortedSet) { 814 return Collections.unmodifiableSortedSet((SortedSet<V>) collection); 815 } else if (collection instanceof Set) { 816 return Collections.unmodifiableSet((Set<V>) collection); 817 } else if (collection instanceof List) { 818 return Collections.unmodifiableList((List<V>) collection); 819 } 820 return Collections.unmodifiableCollection(collection); 821 } 822 823 /** 824 * Returns an unmodifiable view of the specified multimap {@code asMap} entry. 825 * The {@link Entry#setValue} operation throws an {@link 826 * UnsupportedOperationException}, and the collection returned by {@code 827 * getValue} is also an unmodifiable (type-preserving) view. This also has the 828 * side-effect of redefining equals to comply with the Map.Entry contract, and 829 * to avoid a possible nefarious implementation of equals. 830 * 831 * @param entry the entry for which to return an unmodifiable view 832 * @return an unmodifiable view of the entry 833 */ 834 private static <K, V> Map.Entry<K, Collection<V>> unmodifiableAsMapEntry( 835 final Map.Entry<K, Collection<V>> entry) { 836 checkNotNull(entry); 837 return new AbstractMapEntry<K, Collection<V>>() { 838 @Override public K getKey() { 839 return entry.getKey(); 840 } 841 842 @Override public Collection<V> getValue() { 843 return unmodifiableValueCollection(entry.getValue()); 844 } 845 }; 846 } 847 848 /** 849 * Returns an unmodifiable view of the specified collection of entries. The 850 * {@link Entry#setValue} operation throws an {@link 851 * UnsupportedOperationException}. If the specified collection is a {@code 852 * Set}, the returned collection is also a {@code Set}. 853 * 854 * @param entries the entries for which to return an unmodifiable view 855 * @return an unmodifiable view of the entries 856 */ 857 private static <K, V> Collection<Entry<K, V>> unmodifiableEntries( 858 Collection<Entry<K, V>> entries) { 859 if (entries instanceof Set) { 860 return Maps.unmodifiableEntrySet((Set<Entry<K, V>>) entries); 861 } 862 return new Maps.UnmodifiableEntries<K, V>( 863 Collections.unmodifiableCollection(entries)); 864 } 865 866 /** 867 * Returns an unmodifiable view of the specified set of {@code asMap} entries. 868 * The {@link Entry#setValue} operation throws an {@link 869 * UnsupportedOperationException}, as do any operations that attempt to modify 870 * the returned collection. 871 * 872 * @param asMapEntries the {@code asMap} entries for which to return an 873 * unmodifiable view 874 * @return an unmodifiable view of the collection entries 875 */ 876 private static <K, V> Set<Entry<K, Collection<V>>> unmodifiableAsMapEntries( 877 Set<Entry<K, Collection<V>>> asMapEntries) { 878 return new UnmodifiableAsMapEntries<K, V>( 879 Collections.unmodifiableSet(asMapEntries)); 880 } 881 882 /** @see Multimaps#unmodifiableAsMapEntries */ 883 static class UnmodifiableAsMapEntries<K, V> 884 extends ForwardingSet<Entry<K, Collection<V>>> { 885 private final Set<Entry<K, Collection<V>>> delegate; 886 UnmodifiableAsMapEntries(Set<Entry<K, Collection<V>>> delegate) { 887 this.delegate = delegate; 888 } 889 890 @Override protected Set<Entry<K, Collection<V>>> delegate() { 891 return delegate; 892 } 893 894 @Override public Iterator<Entry<K, Collection<V>>> iterator() { 895 final Iterator<Entry<K, Collection<V>>> iterator = delegate.iterator(); 896 return new ForwardingIterator<Entry<K, Collection<V>>>() { 897 @Override protected Iterator<Entry<K, Collection<V>>> delegate() { 898 return iterator; 899 } 900 @Override public Entry<K, Collection<V>> next() { 901 return unmodifiableAsMapEntry(iterator.next()); 902 } 903 }; 904 } 905 906 @Override public Object[] toArray() { 907 return ObjectArrays.toArrayImpl(this); 908 } 909 910 @Override public <T> T[] toArray(T[] array) { 911 return ObjectArrays.toArrayImpl(this, array); 912 } 913 914 @Override public boolean contains(Object o) { 915 return Maps.containsEntryImpl(delegate(), o); 916 } 917 918 @Override public boolean containsAll(Collection<?> c) { 919 return Collections2.containsAll(this, c); 920 } 921 922 @Override public boolean equals(@Nullable Object object) { 923 return Collections2.setEquals(this, object); 924 } 925 } 926 927 /** 928 * Returns a multimap view of the specified map. The multimap is backed by the 929 * map, so changes to the map are reflected in the multimap, and vice versa. 930 * If the map is modified while an iteration over one of the multimap's 931 * collection views is in progress (except through the iterator's own {@code 932 * remove} operation, or through the {@code setValue} operation on a map entry 933 * returned by the iterator), the results of the iteration are undefined. 934 * 935 * <p>The multimap supports mapping removal, which removes the corresponding 936 * mapping from the map. It does not support any operations which might add 937 * mappings, such as {@code put}, {@code putAll} or {@code replaceValues}. 938 * 939 * <p>The returned multimap will be serializable if the specified map is 940 * serializable. 941 * 942 * @param map the backing map for the returned multimap view 943 */ 944 public static <K, V> SetMultimap<K, V> forMap(Map<K, V> map) { 945 return new MapMultimap<K, V>(map); 946 } 947 948 /** @see Multimaps#forMap */ 949 private static class MapMultimap<K, V> 950 implements SetMultimap<K, V>, Serializable { 951 final Map<K, V> map; 952 transient Map<K, Collection<V>> asMap; 953 954 MapMultimap(Map<K, V> map) { 955 this.map = checkNotNull(map); 956 } 957 958 public int size() { 959 return map.size(); 960 } 961 962 public boolean isEmpty() { 963 return map.isEmpty(); 964 } 965 966 public boolean containsKey(Object key) { 967 return map.containsKey(key); 968 } 969 970 public boolean containsValue(Object value) { 971 return map.containsValue(value); 972 } 973 974 public boolean containsEntry(Object key, Object value) { 975 return map.entrySet().contains(Maps.immutableEntry(key, value)); 976 } 977 978 public Set<V> get(final K key) { 979 return new AbstractSet<V>() { 980 @Override public Iterator<V> iterator() { 981 return new Iterator<V>() { 982 int i; 983 984 public boolean hasNext() { 985 return (i == 0) && map.containsKey(key); 986 } 987 988 public V next() { 989 if (!hasNext()) { 990 throw new NoSuchElementException(); 991 } 992 i++; 993 return map.get(key); 994 } 995 996 public void remove() { 997 checkState(i == 1); 998 i = -1; 999 map.remove(key); 1000 } 1001 }; 1002 } 1003 1004 @Override public int size() { 1005 return map.containsKey(key) ? 1 : 0; 1006 } 1007 }; 1008 } 1009 1010 public boolean put(K key, V value) { 1011 throw new UnsupportedOperationException(); 1012 } 1013 1014 public boolean putAll(K key, Iterable<? extends V> values) { 1015 throw new UnsupportedOperationException(); 1016 } 1017 1018 public boolean putAll(Multimap<? extends K, ? extends V> multimap) { 1019 throw new UnsupportedOperationException(); 1020 } 1021 1022 public Set<V> replaceValues(K key, Iterable<? extends V> values) { 1023 throw new UnsupportedOperationException(); 1024 } 1025 1026 public boolean remove(Object key, Object value) { 1027 return map.entrySet().remove(Maps.immutableEntry(key, value)); 1028 } 1029 1030 public Set<V> removeAll(Object key) { 1031 Set<V> values = new HashSet<V>(2); 1032 if (!map.containsKey(key)) { 1033 return values; 1034 } 1035 values.add(map.remove(key)); 1036 return values; 1037 } 1038 1039 public void clear() { 1040 map.clear(); 1041 } 1042 1043 public Set<K> keySet() { 1044 return map.keySet(); 1045 } 1046 1047 public Multiset<K> keys() { 1048 return Multisets.forSet(map.keySet()); 1049 } 1050 1051 public Collection<V> values() { 1052 return map.values(); 1053 } 1054 1055 public Set<Entry<K, V>> entries() { 1056 return map.entrySet(); 1057 } 1058 1059 public Map<K, Collection<V>> asMap() { 1060 Map<K, Collection<V>> result = asMap; 1061 if (result == null) { 1062 asMap = result = new AsMap(); 1063 } 1064 return result; 1065 } 1066 1067 @Override public boolean equals(@Nullable Object object) { 1068 if (object == this) { 1069 return true; 1070 } 1071 if (object instanceof Multimap) { 1072 Multimap<?, ?> that = (Multimap<?, ?>) object; 1073 return this.size() == that.size() && asMap().equals(that.asMap()); 1074 } 1075 return false; 1076 } 1077 1078 @Override public int hashCode() { 1079 return map.hashCode(); 1080 } 1081 1082 private static final MapJoiner joiner 1083 = Joiner.on("], ").withKeyValueSeparator("=[").useForNull("null"); 1084 1085 @Override public String toString() { 1086 if (map.isEmpty()) { 1087 return "{}"; 1088 } 1089 StringBuilder builder = new StringBuilder(map.size() * 16).append('{'); 1090 joiner.appendTo(builder, map); 1091 return builder.append("]}").toString(); 1092 } 1093 1094 /** @see MapMultimap#asMap */ 1095 class AsMapEntries extends AbstractSet<Entry<K, Collection<V>>> { 1096 @Override public int size() { 1097 return map.size(); 1098 } 1099 1100 @Override public Iterator<Entry<K, Collection<V>>> iterator() { 1101 return new Iterator<Entry<K, Collection<V>>>() { 1102 final Iterator<K> keys = map.keySet().iterator(); 1103 1104 public boolean hasNext() { 1105 return keys.hasNext(); 1106 } 1107 public Entry<K, Collection<V>> next() { 1108 final K key = keys.next(); 1109 return new AbstractMapEntry<K, Collection<V>>() { 1110 @Override public K getKey() { 1111 return key; 1112 } 1113 @Override public Collection<V> getValue() { 1114 return get(key); 1115 } 1116 }; 1117 } 1118 public void remove() { 1119 keys.remove(); 1120 } 1121 }; 1122 } 1123 1124 @Override public boolean contains(Object o) { 1125 if (!(o instanceof Entry)) { 1126 return false; 1127 } 1128 Entry<?, ?> entry = (Entry<?, ?>) o; 1129 if (!(entry.getValue() instanceof Set)) { 1130 return false; 1131 } 1132 Set<?> set = (Set<?>) entry.getValue(); 1133 return (set.size() == 1) 1134 && containsEntry(entry.getKey(), set.iterator().next()); 1135 } 1136 1137 @Override public boolean remove(Object o) { 1138 if (!(o instanceof Entry)) { 1139 return false; 1140 } 1141 Entry<?, ?> entry = (Entry<?, ?>) o; 1142 if (!(entry.getValue() instanceof Set)) { 1143 return false; 1144 } 1145 Set<?> set = (Set<?>) entry.getValue(); 1146 return (set.size() == 1) 1147 && map.entrySet().remove( 1148 Maps.immutableEntry(entry.getKey(), set.iterator().next())); 1149 } 1150 } 1151 1152 /** @see MapMultimap#asMap */ 1153 class AsMap extends Maps.ImprovedAbstractMap<K, Collection<V>> { 1154 @Override protected Set<Entry<K, Collection<V>>> createEntrySet() { 1155 return new AsMapEntries(); 1156 } 1157 1158 // The following methods are included for performance. 1159 1160 @Override public boolean containsKey(Object key) { 1161 return map.containsKey(key); 1162 } 1163 1164 @SuppressWarnings("unchecked") 1165 @Override public Collection<V> get(Object key) { 1166 Collection<V> collection = MapMultimap.this.get((K) key); 1167 return collection.isEmpty() ? null : collection; 1168 } 1169 1170 @Override public Collection<V> remove(Object key) { 1171 Collection<V> collection = removeAll(key); 1172 return collection.isEmpty() ? null : collection; 1173 } 1174 } 1175 private static final long serialVersionUID = 7845222491160860175L; 1176 } 1177 1178 /** 1179 * Creates an index {@code ImmutableMultimap} that contains the results of 1180 * applying a specified function to each item in an {@code Iterable} of 1181 * values. Each value will be stored as a value in the resulting multimap, 1182 * yielding a multimap with the same size as the input iterable. The key used 1183 * to store that value in the multimap will be the result of calling the 1184 * function on that value. The resulting multimap is created as an immutable 1185 * snapshot, it does <em>not</em> reflect subsequent changes on the input 1186 * iterable. 1187 * 1188 * <p>For example, <pre class="code"> {@code 1189 * 1190 * List<String> badGuys 1191 * = Arrays.asList("Inky", "Blinky", "Pinky", "Pinky", "Clyde"); 1192 * Function<String, Integer> stringLengthFunction = ...; 1193 * Multimap<Integer, String> index 1194 * = Multimaps.index(badGuys, stringLengthFunction); 1195 * System.out.println(index);}</pre> 1196 * 1197 * prints <pre class="code"> {@code 1198 * 1199 * {4=[Inky], 5=[Pinky, Pinky, Clyde], 6=[Blinky]}}</pre> 1200 * 1201 * <p>The returned multimap is serializable if its keys and values are all 1202 * serializable. 1203 * 1204 * @param values the values to use when constructing the {@code 1205 * ImmutableMultimap} 1206 * @param keyFunction the function used to produce the key for each value 1207 * @return {@code ImmutableMultimap} mapping the result of evaluating the 1208 * function {@code keyFunction} on each value in the input collection to 1209 * that value 1210 * @throws NullPointerException if any of the following cases is true: <ul> 1211 * <li> {@code values} is null 1212 * <li> {@code keyFunction} is null 1213 * <li> An element in {@code values} is null 1214 * <li> {@code keyFunction} returns null for any element of {@code values} 1215 * </ul> 1216 */ 1217 public static <K, V> ImmutableListMultimap<K, V> index( 1218 Iterable<V> values, Function<? super V, K> keyFunction) { 1219 checkNotNull(keyFunction); 1220 ImmutableListMultimap.Builder<K, V> builder 1221 = ImmutableListMultimap.builder(); 1222 for (V value : values) { 1223 Preconditions.checkNotNull(value, values); 1224 builder.put(keyFunction.apply(value), value); 1225 } 1226 return builder.build(); 1227 } 1228 } 1229