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