• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
22 import static com.google.common.collect.CollectPreconditions.checkRemove;
23 import static java.util.Objects.requireNonNull;
24 
25 import com.google.common.annotations.GwtCompatible;
26 import com.google.common.base.Objects;
27 import com.google.common.base.Predicate;
28 import com.google.common.base.Predicates;
29 import com.google.common.collect.Multiset.Entry;
30 import com.google.common.math.IntMath;
31 import com.google.common.primitives.Ints;
32 import com.google.errorprone.annotations.CanIgnoreReturnValue;
33 import com.google.errorprone.annotations.concurrent.LazyInit;
34 import java.io.Serializable;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.Comparator;
39 import java.util.Iterator;
40 import java.util.NoSuchElementException;
41 import java.util.Set;
42 import java.util.Spliterator;
43 import java.util.function.Function;
44 import java.util.function.Supplier;
45 import java.util.function.ToIntFunction;
46 import java.util.stream.Collector;
47 import javax.annotation.CheckForNull;
48 import org.checkerframework.checker.nullness.qual.Nullable;
49 
50 /**
51  * Provides static utility methods for creating and working with {@link Multiset} instances.
52  *
53  * <p>See the Guava User Guide article on <a href=
54  * "https://github.com/google/guava/wiki/CollectionUtilitiesExplained#multisets">{@code
55  * Multisets}</a>.
56  *
57  * @author Kevin Bourrillion
58  * @author Mike Bostock
59  * @author Louis Wasserman
60  * @since 2.0
61  */
62 @GwtCompatible
63 @ElementTypesAreNonnullByDefault
64 public final class Multisets {
Multisets()65   private Multisets() {}
66 
67   /**
68    * Returns a {@code Collector} that accumulates elements into a multiset created via the specified
69    * {@code Supplier}, whose elements are the result of applying {@code elementFunction} to the
70    * inputs, with counts equal to the result of applying {@code countFunction} to the inputs.
71    * Elements are added in encounter order.
72    *
73    * <p>If the mapped elements contain duplicates (according to {@link Object#equals}), the element
74    * will be added more than once, with the count summed over all appearances of the element.
75    *
76    * <p>Note that {@code stream.collect(toMultiset(function, e -> 1, supplier))} is equivalent to
77    * {@code stream.map(function).collect(Collectors.toCollection(supplier))}.
78    *
79    * <p>To collect to an {@link ImmutableMultiset}, use {@link
80    * ImmutableMultiset#toImmutableMultiset}.
81    *
82    * @since 22.0
83    */
84   public static <T extends @Nullable Object, E extends @Nullable Object, M extends Multiset<E>>
toMultiset( Function<? super T, E> elementFunction, ToIntFunction<? super T> countFunction, Supplier<M> multisetSupplier)85       Collector<T, ?, M> toMultiset(
86           Function<? super T, E> elementFunction,
87           ToIntFunction<? super T> countFunction,
88           Supplier<M> multisetSupplier) {
89     return CollectCollectors.toMultiset(elementFunction, countFunction, multisetSupplier);
90   }
91 
92   /**
93    * Returns an unmodifiable view of the specified multiset. Query operations on the returned
94    * multiset "read through" to the specified multiset, and attempts to modify the returned multiset
95    * result in an {@link UnsupportedOperationException}.
96    *
97    * <p>The returned multiset will be serializable if the specified multiset is serializable.
98    *
99    * @param multiset the multiset for which an unmodifiable view is to be generated
100    * @return an unmodifiable view of the multiset
101    */
unmodifiableMultiset( Multiset<? extends E> multiset)102   public static <E extends @Nullable Object> Multiset<E> unmodifiableMultiset(
103       Multiset<? extends E> multiset) {
104     if (multiset instanceof UnmodifiableMultiset || multiset instanceof ImmutableMultiset) {
105       @SuppressWarnings("unchecked") // Since it's unmodifiable, the covariant cast is safe
106       Multiset<E> result = (Multiset<E>) multiset;
107       return result;
108     }
109     return new UnmodifiableMultiset<E>(checkNotNull(multiset));
110   }
111 
112   /**
113    * Simply returns its argument.
114    *
115    * @deprecated no need to use this
116    * @since 10.0
117    */
118   @Deprecated
unmodifiableMultiset(ImmutableMultiset<E> multiset)119   public static <E> Multiset<E> unmodifiableMultiset(ImmutableMultiset<E> multiset) {
120     return checkNotNull(multiset);
121   }
122 
123   static class UnmodifiableMultiset<E extends @Nullable Object> extends ForwardingMultiset<E>
124       implements Serializable {
125     final Multiset<? extends E> delegate;
126 
UnmodifiableMultiset(Multiset<? extends E> delegate)127     UnmodifiableMultiset(Multiset<? extends E> delegate) {
128       this.delegate = delegate;
129     }
130 
131     @SuppressWarnings("unchecked")
132     @Override
delegate()133     protected Multiset<E> delegate() {
134       // This is safe because all non-covariant methods are overridden
135       return (Multiset<E>) delegate;
136     }
137 
138     @LazyInit @CheckForNull transient Set<E> elementSet;
139 
createElementSet()140     Set<E> createElementSet() {
141       return Collections.<E>unmodifiableSet(delegate.elementSet());
142     }
143 
144     @Override
elementSet()145     public Set<E> elementSet() {
146       Set<E> es = elementSet;
147       return (es == null) ? elementSet = createElementSet() : es;
148     }
149 
150     @LazyInit @CheckForNull transient Set<Multiset.Entry<E>> entrySet;
151 
152     @SuppressWarnings("unchecked")
153     @Override
entrySet()154     public Set<Multiset.Entry<E>> entrySet() {
155       Set<Multiset.Entry<E>> es = entrySet;
156       return (es == null)
157           // Safe because the returned set is made unmodifiable and Entry
158           // itself is readonly
159           ? entrySet = (Set) Collections.unmodifiableSet(delegate.entrySet())
160           : es;
161     }
162 
163     @Override
iterator()164     public Iterator<E> iterator() {
165       return Iterators.<E>unmodifiableIterator(delegate.iterator());
166     }
167 
168     @Override
add(@arametricNullness E element)169     public boolean add(@ParametricNullness E element) {
170       throw new UnsupportedOperationException();
171     }
172 
173     @Override
add(@arametricNullness E element, int occurrences)174     public int add(@ParametricNullness E element, int occurrences) {
175       throw new UnsupportedOperationException();
176     }
177 
178     @Override
addAll(Collection<? extends E> elementsToAdd)179     public boolean addAll(Collection<? extends E> elementsToAdd) {
180       throw new UnsupportedOperationException();
181     }
182 
183     @Override
remove(@heckForNull Object element)184     public boolean remove(@CheckForNull Object element) {
185       throw new UnsupportedOperationException();
186     }
187 
188     @Override
remove(@heckForNull Object element, int occurrences)189     public int remove(@CheckForNull Object element, int occurrences) {
190       throw new UnsupportedOperationException();
191     }
192 
193     @Override
removeAll(Collection<?> elementsToRemove)194     public boolean removeAll(Collection<?> elementsToRemove) {
195       throw new UnsupportedOperationException();
196     }
197 
198     @Override
removeIf(java.util.function.Predicate<? super E> filter)199     public boolean removeIf(java.util.function.Predicate<? super E> filter) {
200       throw new UnsupportedOperationException();
201     }
202 
203     @Override
retainAll(Collection<?> elementsToRetain)204     public boolean retainAll(Collection<?> elementsToRetain) {
205       throw new UnsupportedOperationException();
206     }
207 
208     @Override
clear()209     public void clear() {
210       throw new UnsupportedOperationException();
211     }
212 
213     @Override
setCount(@arametricNullness E element, int count)214     public int setCount(@ParametricNullness E element, int count) {
215       throw new UnsupportedOperationException();
216     }
217 
218     @Override
setCount(@arametricNullness E element, int oldCount, int newCount)219     public boolean setCount(@ParametricNullness E element, int oldCount, int newCount) {
220       throw new UnsupportedOperationException();
221     }
222 
223     private static final long serialVersionUID = 0;
224   }
225 
226   /**
227    * Returns an unmodifiable view of the specified sorted multiset. Query operations on the returned
228    * multiset "read through" to the specified multiset, and attempts to modify the returned multiset
229    * result in an {@link UnsupportedOperationException}.
230    *
231    * <p>The returned multiset will be serializable if the specified multiset is serializable.
232    *
233    * @param sortedMultiset the sorted multiset for which an unmodifiable view is to be generated
234    * @return an unmodifiable view of the multiset
235    * @since 11.0
236    */
unmodifiableSortedMultiset( SortedMultiset<E> sortedMultiset)237   public static <E extends @Nullable Object> SortedMultiset<E> unmodifiableSortedMultiset(
238       SortedMultiset<E> sortedMultiset) {
239     // it's in its own file so it can be emulated for GWT
240     return new UnmodifiableSortedMultiset<E>(checkNotNull(sortedMultiset));
241   }
242 
243   /**
244    * Returns an immutable multiset entry with the specified element and count. The entry will be
245    * serializable if {@code e} is.
246    *
247    * @param e the element to be associated with the returned entry
248    * @param n the count to be associated with the returned entry
249    * @throws IllegalArgumentException if {@code n} is negative
250    */
immutableEntry( @arametricNullness E e, int n)251   public static <E extends @Nullable Object> Multiset.Entry<E> immutableEntry(
252       @ParametricNullness E e, int n) {
253     return new ImmutableEntry<E>(e, n);
254   }
255 
256   static class ImmutableEntry<E extends @Nullable Object> extends AbstractEntry<E>
257       implements Serializable {
258     @ParametricNullness private final E element;
259     private final int count;
260 
ImmutableEntry(@arametricNullness E element, int count)261     ImmutableEntry(@ParametricNullness E element, int count) {
262       this.element = element;
263       this.count = count;
264       checkNonnegative(count, "count");
265     }
266 
267     @Override
268     @ParametricNullness
getElement()269     public final E getElement() {
270       return element;
271     }
272 
273     @Override
getCount()274     public final int getCount() {
275       return count;
276     }
277 
278     @CheckForNull
nextInBucket()279     public ImmutableEntry<E> nextInBucket() {
280       return null;
281     }
282 
283     private static final long serialVersionUID = 0;
284   }
285 
286   /**
287    * Returns a view of the elements of {@code unfiltered} that satisfy a predicate. The returned
288    * multiset is a live view of {@code unfiltered}; changes to one affect the other.
289    *
290    * <p>The resulting multiset's iterators, and those of its {@code entrySet()} and {@code
291    * elementSet()}, do not support {@code remove()}. However, all other multiset methods supported
292    * by {@code unfiltered} are supported by the returned multiset. When given an element that
293    * doesn't satisfy the predicate, the multiset's {@code add()} and {@code addAll()} methods throw
294    * an {@link IllegalArgumentException}. When methods such as {@code removeAll()} and {@code
295    * clear()} are called on the filtered multiset, only elements that satisfy the filter will be
296    * removed from the underlying multiset.
297    *
298    * <p>The returned multiset isn't threadsafe or serializable, even if {@code unfiltered} is.
299    *
300    * <p>Many of the filtered multiset's methods, such as {@code size()}, iterate across every
301    * element in the underlying multiset and determine which elements satisfy the filter. When a live
302    * view is <i>not</i> needed, it may be faster to copy the returned multiset and use the copy.
303    *
304    * <p><b>Warning:</b> {@code predicate} must be <i>consistent with equals</i>, as documented at
305    * {@link Predicate#apply}. Do not provide a predicate such as {@code
306    * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. (See {@link
307    * Iterables#filter(Iterable, Class)} for related functionality.)
308    *
309    * @since 14.0
310    */
filter( Multiset<E> unfiltered, Predicate<? super E> predicate)311   public static <E extends @Nullable Object> Multiset<E> filter(
312       Multiset<E> unfiltered, Predicate<? super E> predicate) {
313     if (unfiltered instanceof FilteredMultiset) {
314       // Support clear(), removeAll(), and retainAll() when filtering a filtered
315       // collection.
316       FilteredMultiset<E> filtered = (FilteredMultiset<E>) unfiltered;
317       Predicate<E> combinedPredicate = Predicates.<E>and(filtered.predicate, predicate);
318       return new FilteredMultiset<E>(filtered.unfiltered, combinedPredicate);
319     }
320     return new FilteredMultiset<E>(unfiltered, predicate);
321   }
322 
323   private static final class FilteredMultiset<E extends @Nullable Object> extends ViewMultiset<E> {
324     final Multiset<E> unfiltered;
325     final Predicate<? super E> predicate;
326 
FilteredMultiset(Multiset<E> unfiltered, Predicate<? super E> predicate)327     FilteredMultiset(Multiset<E> unfiltered, Predicate<? super E> predicate) {
328       this.unfiltered = checkNotNull(unfiltered);
329       this.predicate = checkNotNull(predicate);
330     }
331 
332     @Override
iterator()333     public UnmodifiableIterator<E> iterator() {
334       return Iterators.filter(unfiltered.iterator(), predicate);
335     }
336 
337     @Override
createElementSet()338     Set<E> createElementSet() {
339       return Sets.filter(unfiltered.elementSet(), predicate);
340     }
341 
342     @Override
elementIterator()343     Iterator<E> elementIterator() {
344       throw new AssertionError("should never be called");
345     }
346 
347     @Override
createEntrySet()348     Set<Entry<E>> createEntrySet() {
349       return Sets.filter(
350           unfiltered.entrySet(),
351           new Predicate<Entry<E>>() {
352             @Override
353             public boolean apply(Entry<E> entry) {
354               return predicate.apply(entry.getElement());
355             }
356           });
357     }
358 
359     @Override
entryIterator()360     Iterator<Entry<E>> entryIterator() {
361       throw new AssertionError("should never be called");
362     }
363 
364     @Override
count(@heckForNull Object element)365     public int count(@CheckForNull Object element) {
366       int count = unfiltered.count(element);
367       if (count > 0) {
368         @SuppressWarnings("unchecked") // element is equal to an E
369         E e = (E) element;
370         return predicate.apply(e) ? count : 0;
371       }
372       return 0;
373     }
374 
375     @Override
add(@arametricNullness E element, int occurrences)376     public int add(@ParametricNullness E element, int occurrences) {
377       checkArgument(
378           predicate.apply(element), "Element %s does not match predicate %s", element, predicate);
379       return unfiltered.add(element, occurrences);
380     }
381 
382     @Override
remove(@heckForNull Object element, int occurrences)383     public int remove(@CheckForNull Object element, int occurrences) {
384       checkNonnegative(occurrences, "occurrences");
385       if (occurrences == 0) {
386         return count(element);
387       } else {
388         return contains(element) ? unfiltered.remove(element, occurrences) : 0;
389       }
390     }
391   }
392 
393   /**
394    * Returns the expected number of distinct elements given the specified elements. The number of
395    * distinct elements is only computed if {@code elements} is an instance of {@code Multiset};
396    * otherwise the default value of 11 is returned.
397    */
398   static int inferDistinctElements(Iterable<?> elements) {
399     if (elements instanceof Multiset) {
400       return ((Multiset<?>) elements).elementSet().size();
401     }
402     return 11; // initial capacity will be rounded up to 16
403   }
404 
405   /**
406    * Returns an unmodifiable view of the union of two multisets. In the returned multiset, the count
407    * of each element is the <i>maximum</i> of its counts in the two backing multisets. The iteration
408    * order of the returned multiset matches that of the element set of {@code multiset1} followed by
409    * the members of the element set of {@code multiset2} that are not contained in {@code
410    * multiset1}, with repeated occurrences of the same element appearing consecutively.
411    *
412    * <p>Results are undefined if {@code multiset1} and {@code multiset2} are based on different
413    * equivalence relations (as {@code HashMultiset} and {@code TreeMultiset} are).
414    *
415    * @since 14.0
416    */
417   public static <E extends @Nullable Object> Multiset<E> union(
418       final Multiset<? extends E> multiset1, final Multiset<? extends E> multiset2) {
419     checkNotNull(multiset1);
420     checkNotNull(multiset2);
421 
422     return new ViewMultiset<E>() {
423       @Override
424       public boolean contains(@CheckForNull Object element) {
425         return multiset1.contains(element) || multiset2.contains(element);
426       }
427 
428       @Override
429       public boolean isEmpty() {
430         return multiset1.isEmpty() && multiset2.isEmpty();
431       }
432 
433       @Override
434       public int count(@CheckForNull Object element) {
435         return Math.max(multiset1.count(element), multiset2.count(element));
436       }
437 
438       @Override
439       Set<E> createElementSet() {
440         return Sets.union(multiset1.elementSet(), multiset2.elementSet());
441       }
442 
443       @Override
444       Iterator<E> elementIterator() {
445         throw new AssertionError("should never be called");
446       }
447 
448       @Override
449       Iterator<Entry<E>> entryIterator() {
450         final Iterator<? extends Entry<? extends E>> iterator1 = multiset1.entrySet().iterator();
451         final Iterator<? extends Entry<? extends E>> iterator2 = multiset2.entrySet().iterator();
452         // TODO(lowasser): consider making the entries live views
453         return new AbstractIterator<Entry<E>>() {
454           @Override
455           @CheckForNull
456           protected Entry<E> computeNext() {
457             if (iterator1.hasNext()) {
458               Entry<? extends E> entry1 = iterator1.next();
459               E element = entry1.getElement();
460               int count = Math.max(entry1.getCount(), multiset2.count(element));
461               return immutableEntry(element, count);
462             }
463             while (iterator2.hasNext()) {
464               Entry<? extends E> entry2 = iterator2.next();
465               E element = entry2.getElement();
466               if (!multiset1.contains(element)) {
467                 return immutableEntry(element, entry2.getCount());
468               }
469             }
470             return endOfData();
471           }
472         };
473       }
474     };
475   }
476 
477   /**
478    * Returns an unmodifiable view of the intersection of two multisets. In the returned multiset,
479    * the count of each element is the <i>minimum</i> of its counts in the two backing multisets,
480    * with elements that would have a count of 0 not included. The iteration order of the returned
481    * multiset matches that of the element set of {@code multiset1}, with repeated occurrences of the
482    * same element appearing consecutively.
483    *
484    * <p>Results are undefined if {@code multiset1} and {@code multiset2} are based on different
485    * equivalence relations (as {@code HashMultiset} and {@code TreeMultiset} are).
486    *
487    * @since 2.0
488    */
489   public static <E extends @Nullable Object> Multiset<E> intersection(
490       final Multiset<E> multiset1, final Multiset<?> multiset2) {
491     checkNotNull(multiset1);
492     checkNotNull(multiset2);
493 
494     return new ViewMultiset<E>() {
495       @Override
496       public int count(@CheckForNull Object element) {
497         int count1 = multiset1.count(element);
498         return (count1 == 0) ? 0 : Math.min(count1, multiset2.count(element));
499       }
500 
501       @Override
502       Set<E> createElementSet() {
503         return Sets.intersection(multiset1.elementSet(), multiset2.elementSet());
504       }
505 
506       @Override
507       Iterator<E> elementIterator() {
508         throw new AssertionError("should never be called");
509       }
510 
511       @Override
512       Iterator<Entry<E>> entryIterator() {
513         final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
514         // TODO(lowasser): consider making the entries live views
515         return new AbstractIterator<Entry<E>>() {
516           @Override
517           @CheckForNull
518           protected Entry<E> computeNext() {
519             while (iterator1.hasNext()) {
520               Entry<E> entry1 = iterator1.next();
521               E element = entry1.getElement();
522               int count = Math.min(entry1.getCount(), multiset2.count(element));
523               if (count > 0) {
524                 return immutableEntry(element, count);
525               }
526             }
527             return endOfData();
528           }
529         };
530       }
531     };
532   }
533 
534   /**
535    * Returns an unmodifiable view of the sum of two multisets. In the returned multiset, the count
536    * of each element is the <i>sum</i> of its counts in the two backing multisets. The iteration
537    * order of the returned multiset matches that of the element set of {@code multiset1} followed by
538    * the members of the element set of {@code multiset2} that are not contained in {@code
539    * multiset1}, with repeated occurrences of the same element appearing consecutively.
540    *
541    * <p>Results are undefined if {@code multiset1} and {@code multiset2} are based on different
542    * equivalence relations (as {@code HashMultiset} and {@code TreeMultiset} are).
543    *
544    * @since 14.0
545    */
546   public static <E extends @Nullable Object> Multiset<E> sum(
547       final Multiset<? extends E> multiset1, final Multiset<? extends E> multiset2) {
548     checkNotNull(multiset1);
549     checkNotNull(multiset2);
550 
551     // TODO(lowasser): consider making the entries live views
552     return new ViewMultiset<E>() {
553       @Override
554       public boolean contains(@CheckForNull Object element) {
555         return multiset1.contains(element) || multiset2.contains(element);
556       }
557 
558       @Override
559       public boolean isEmpty() {
560         return multiset1.isEmpty() && multiset2.isEmpty();
561       }
562 
563       @Override
564       public int size() {
565         return IntMath.saturatedAdd(multiset1.size(), multiset2.size());
566       }
567 
568       @Override
569       public int count(@CheckForNull Object element) {
570         return multiset1.count(element) + multiset2.count(element);
571       }
572 
573       @Override
574       Set<E> createElementSet() {
575         return Sets.union(multiset1.elementSet(), multiset2.elementSet());
576       }
577 
578       @Override
579       Iterator<E> elementIterator() {
580         throw new AssertionError("should never be called");
581       }
582 
583       @Override
584       Iterator<Entry<E>> entryIterator() {
585         final Iterator<? extends Entry<? extends E>> iterator1 = multiset1.entrySet().iterator();
586         final Iterator<? extends Entry<? extends E>> iterator2 = multiset2.entrySet().iterator();
587         return new AbstractIterator<Entry<E>>() {
588           @Override
589           @CheckForNull
590           protected Entry<E> computeNext() {
591             if (iterator1.hasNext()) {
592               Entry<? extends E> entry1 = iterator1.next();
593               E element = entry1.getElement();
594               int count = entry1.getCount() + multiset2.count(element);
595               return immutableEntry(element, count);
596             }
597             while (iterator2.hasNext()) {
598               Entry<? extends E> entry2 = iterator2.next();
599               E element = entry2.getElement();
600               if (!multiset1.contains(element)) {
601                 return immutableEntry(element, entry2.getCount());
602               }
603             }
604             return endOfData();
605           }
606         };
607       }
608     };
609   }
610 
611   /**
612    * Returns an unmodifiable view of the difference of two multisets. In the returned multiset, the
613    * count of each element is the result of the <i>zero-truncated subtraction</i> of its count in
614    * the second multiset from its count in the first multiset, with elements that would have a count
615    * of 0 not included. The iteration order of the returned multiset matches that of the element set
616    * of {@code multiset1}, with repeated occurrences of the same element appearing consecutively.
617    *
618    * <p>Results are undefined if {@code multiset1} and {@code multiset2} are based on different
619    * equivalence relations (as {@code HashMultiset} and {@code TreeMultiset} are).
620    *
621    * @since 14.0
622    */
623   public static <E extends @Nullable Object> Multiset<E> difference(
624       final Multiset<E> multiset1, final Multiset<?> multiset2) {
625     checkNotNull(multiset1);
626     checkNotNull(multiset2);
627 
628     // TODO(lowasser): consider making the entries live views
629     return new ViewMultiset<E>() {
630       @Override
631       public int count(@CheckForNull Object element) {
632         int count1 = multiset1.count(element);
633         return (count1 == 0) ? 0 : Math.max(0, count1 - multiset2.count(element));
634       }
635 
636       @Override
637       public void clear() {
638         throw new UnsupportedOperationException();
639       }
640 
641       @Override
642       Iterator<E> elementIterator() {
643         final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
644         return new AbstractIterator<E>() {
645           @Override
646           @CheckForNull
647           protected E computeNext() {
648             while (iterator1.hasNext()) {
649               Entry<E> entry1 = iterator1.next();
650               E element = entry1.getElement();
651               if (entry1.getCount() > multiset2.count(element)) {
652                 return element;
653               }
654             }
655             return endOfData();
656           }
657         };
658       }
659 
660       @Override
661       Iterator<Entry<E>> entryIterator() {
662         final Iterator<Entry<E>> iterator1 = multiset1.entrySet().iterator();
663         return new AbstractIterator<Entry<E>>() {
664           @Override
665           @CheckForNull
666           protected Entry<E> computeNext() {
667             while (iterator1.hasNext()) {
668               Entry<E> entry1 = iterator1.next();
669               E element = entry1.getElement();
670               int count = entry1.getCount() - multiset2.count(element);
671               if (count > 0) {
672                 return immutableEntry(element, count);
673               }
674             }
675             return endOfData();
676           }
677         };
678       }
679 
680       @Override
681       int distinctElements() {
682         return Iterators.size(entryIterator());
683       }
684     };
685   }
686 
687   /**
688    * Returns {@code true} if {@code subMultiset.count(o) <= superMultiset.count(o)} for all {@code
689    * o}.
690    *
691    * @since 10.0
692    */
693   @CanIgnoreReturnValue
694   public static boolean containsOccurrences(Multiset<?> superMultiset, Multiset<?> subMultiset) {
695     checkNotNull(superMultiset);
696     checkNotNull(subMultiset);
697     for (Entry<?> entry : subMultiset.entrySet()) {
698       int superCount = superMultiset.count(entry.getElement());
699       if (superCount < entry.getCount()) {
700         return false;
701       }
702     }
703     return true;
704   }
705 
706   /**
707    * Modifies {@code multisetToModify} so that its count for an element {@code e} is at most {@code
708    * multisetToRetain.count(e)}.
709    *
710    * <p>To be precise, {@code multisetToModify.count(e)} is set to {@code
711    * Math.min(multisetToModify.count(e), multisetToRetain.count(e))}. This is similar to {@link
712    * #intersection(Multiset, Multiset) intersection} {@code (multisetToModify, multisetToRetain)},
713    * but mutates {@code multisetToModify} instead of returning a view.
714    *
715    * <p>In contrast, {@code multisetToModify.retainAll(multisetToRetain)} keeps all occurrences of
716    * elements that appear at all in {@code multisetToRetain}, and deletes all occurrences of all
717    * other elements.
718    *
719    * @return {@code true} if {@code multisetToModify} was changed as a result of this operation
720    * @since 10.0
721    */
722   @CanIgnoreReturnValue
723   public static boolean retainOccurrences(
724       Multiset<?> multisetToModify, Multiset<?> multisetToRetain) {
725     return retainOccurrencesImpl(multisetToModify, multisetToRetain);
726   }
727 
728   /** Delegate implementation which cares about the element type. */
729   private static <E extends @Nullable Object> boolean retainOccurrencesImpl(
730       Multiset<E> multisetToModify, Multiset<?> occurrencesToRetain) {
731     checkNotNull(multisetToModify);
732     checkNotNull(occurrencesToRetain);
733     // Avoiding ConcurrentModificationExceptions is tricky.
734     Iterator<Entry<E>> entryIterator = multisetToModify.entrySet().iterator();
735     boolean changed = false;
736     while (entryIterator.hasNext()) {
737       Entry<E> entry = entryIterator.next();
738       int retainCount = occurrencesToRetain.count(entry.getElement());
739       if (retainCount == 0) {
740         entryIterator.remove();
741         changed = true;
742       } else if (retainCount < entry.getCount()) {
743         multisetToModify.setCount(entry.getElement(), retainCount);
744         changed = true;
745       }
746     }
747     return changed;
748   }
749 
750   /**
751    * For each occurrence of an element {@code e} in {@code occurrencesToRemove}, removes one
752    * occurrence of {@code e} in {@code multisetToModify}.
753    *
754    * <p>Equivalently, this method modifies {@code multisetToModify} so that {@code
755    * multisetToModify.count(e)} is set to {@code Math.max(0, multisetToModify.count(e) -
756    * Iterables.frequency(occurrencesToRemove, e))}.
757    *
758    * <p>This is <i>not</i> the same as {@code multisetToModify.} {@link Multiset#removeAll
759    * removeAll}{@code (occurrencesToRemove)}, which removes all occurrences of elements that appear
760    * in {@code occurrencesToRemove}. However, this operation <i>is</i> equivalent to, albeit
761    * sometimes more efficient than, the following:
762    *
763    * <pre>{@code
764    * for (E e : occurrencesToRemove) {
765    *   multisetToModify.remove(e);
766    * }
767    * }</pre>
768    *
769    * @return {@code true} if {@code multisetToModify} was changed as a result of this operation
770    * @since 18.0 (present in 10.0 with a requirement that the second parameter be a {@code
771    *     Multiset})
772    */
773   @CanIgnoreReturnValue
774   public static boolean removeOccurrences(
775       Multiset<?> multisetToModify, Iterable<?> occurrencesToRemove) {
776     if (occurrencesToRemove instanceof Multiset) {
777       return removeOccurrences(multisetToModify, (Multiset<?>) occurrencesToRemove);
778     } else {
779       checkNotNull(multisetToModify);
780       checkNotNull(occurrencesToRemove);
781       boolean changed = false;
782       for (Object o : occurrencesToRemove) {
783         changed |= multisetToModify.remove(o);
784       }
785       return changed;
786     }
787   }
788 
789   /**
790    * For each occurrence of an element {@code e} in {@code occurrencesToRemove}, removes one
791    * occurrence of {@code e} in {@code multisetToModify}.
792    *
793    * <p>Equivalently, this method modifies {@code multisetToModify} so that {@code
794    * multisetToModify.count(e)} is set to {@code Math.max(0, multisetToModify.count(e) -
795    * occurrencesToRemove.count(e))}.
796    *
797    * <p>This is <i>not</i> the same as {@code multisetToModify.} {@link Multiset#removeAll
798    * removeAll}{@code (occurrencesToRemove)}, which removes all occurrences of elements that appear
799    * in {@code occurrencesToRemove}. However, this operation <i>is</i> equivalent to, albeit
800    * sometimes more efficient than, the following:
801    *
802    * <pre>{@code
803    * for (E e : occurrencesToRemove) {
804    *   multisetToModify.remove(e);
805    * }
806    * }</pre>
807    *
808    * @return {@code true} if {@code multisetToModify} was changed as a result of this operation
809    * @since 10.0 (missing in 18.0 when only the overload taking an {@code Iterable} was present)
810    */
811   @CanIgnoreReturnValue
812   public static boolean removeOccurrences(
813       Multiset<?> multisetToModify, Multiset<?> occurrencesToRemove) {
814     checkNotNull(multisetToModify);
815     checkNotNull(occurrencesToRemove);
816 
817     boolean changed = false;
818     Iterator<? extends Entry<?>> entryIterator = multisetToModify.entrySet().iterator();
819     while (entryIterator.hasNext()) {
820       Entry<?> entry = entryIterator.next();
821       int removeCount = occurrencesToRemove.count(entry.getElement());
822       if (removeCount >= entry.getCount()) {
823         entryIterator.remove();
824         changed = true;
825       } else if (removeCount > 0) {
826         multisetToModify.remove(entry.getElement(), removeCount);
827         changed = true;
828       }
829     }
830     return changed;
831   }
832 
833   /**
834    * Implementation of the {@code equals}, {@code hashCode}, and {@code toString} methods of {@link
835    * Multiset.Entry}.
836    */
837   abstract static class AbstractEntry<E extends @Nullable Object> implements Multiset.Entry<E> {
838     /**
839      * Indicates whether an object equals this entry, following the behavior specified in {@link
840      * Multiset.Entry#equals}.
841      */
842     @Override
843     public boolean equals(@CheckForNull Object object) {
844       if (object instanceof Multiset.Entry) {
845         Multiset.Entry<?> that = (Multiset.Entry<?>) object;
846         return this.getCount() == that.getCount()
847             && Objects.equal(this.getElement(), that.getElement());
848       }
849       return false;
850     }
851 
852     /**
853      * Return this entry's hash code, following the behavior specified in {@link
854      * Multiset.Entry#hashCode}.
855      */
856     @Override
857     public int hashCode() {
858       E e = getElement();
859       return ((e == null) ? 0 : e.hashCode()) ^ getCount();
860     }
861 
862     /**
863      * Returns a string representation of this multiset entry. The string representation consists of
864      * the associated element if the associated count is one, and otherwise the associated element
865      * followed by the characters " x " (space, x and space) followed by the count. Elements and
866      * counts are converted to strings as by {@code String.valueOf}.
867      */
868     @Override
869     public String toString() {
870       String text = String.valueOf(getElement());
871       int n = getCount();
872       return (n == 1) ? text : (text + " x " + n);
873     }
874   }
875 
876   /** An implementation of {@link Multiset#equals}. */
877   static boolean equalsImpl(Multiset<?> multiset, @CheckForNull Object object) {
878     if (object == multiset) {
879       return true;
880     }
881     if (object instanceof Multiset) {
882       Multiset<?> that = (Multiset<?>) object;
883       /*
884        * We can't simply check whether the entry sets are equal, since that
885        * approach fails when a TreeMultiset has a comparator that returns 0
886        * when passed unequal elements.
887        */
888 
889       if (multiset.size() != that.size() || multiset.entrySet().size() != that.entrySet().size()) {
890         return false;
891       }
892       for (Entry<?> entry : that.entrySet()) {
893         if (multiset.count(entry.getElement()) != entry.getCount()) {
894           return false;
895         }
896       }
897       return true;
898     }
899     return false;
900   }
901 
902   /** An implementation of {@link Multiset#addAll}. */
903   static <E extends @Nullable Object> boolean addAllImpl(
904       Multiset<E> self, Collection<? extends E> elements) {
905     checkNotNull(self);
906     checkNotNull(elements);
907     if (elements instanceof Multiset) {
908       return addAllImpl(self, cast(elements));
909     } else if (elements.isEmpty()) {
910       return false;
911     } else {
912       return Iterators.addAll(self, elements.iterator());
913     }
914   }
915 
916   /** A specialization of {@code addAllImpl} for when {@code elements} is itself a Multiset. */
917   private static <E extends @Nullable Object> boolean addAllImpl(
918       Multiset<E> self, Multiset<? extends E> elements) {
919     if (elements.isEmpty()) {
920       return false;
921     }
922     elements.forEachEntry(self::add);
923     return true;
924   }
925 
926   /** An implementation of {@link Multiset#removeAll}. */
927   static boolean removeAllImpl(Multiset<?> self, Collection<?> elementsToRemove) {
928     Collection<?> collection =
929         (elementsToRemove instanceof Multiset)
930             ? ((Multiset<?>) elementsToRemove).elementSet()
931             : elementsToRemove;
932 
933     return self.elementSet().removeAll(collection);
934   }
935 
936   /** An implementation of {@link Multiset#retainAll}. */
937   static boolean retainAllImpl(Multiset<?> self, Collection<?> elementsToRetain) {
938     checkNotNull(elementsToRetain);
939     Collection<?> collection =
940         (elementsToRetain instanceof Multiset)
941             ? ((Multiset<?>) elementsToRetain).elementSet()
942             : elementsToRetain;
943 
944     return self.elementSet().retainAll(collection);
945   }
946 
947   /** An implementation of {@link Multiset#setCount(Object, int)}. */
948   static <E extends @Nullable Object> int setCountImpl(
949       Multiset<E> self, @ParametricNullness E element, int count) {
950     checkNonnegative(count, "count");
951 
952     int oldCount = self.count(element);
953 
954     int delta = count - oldCount;
955     if (delta > 0) {
956       self.add(element, delta);
957     } else if (delta < 0) {
958       self.remove(element, -delta);
959     }
960 
961     return oldCount;
962   }
963 
964   /** An implementation of {@link Multiset#setCount(Object, int, int)}. */
965   static <E extends @Nullable Object> boolean setCountImpl(
966       Multiset<E> self, @ParametricNullness E element, int oldCount, int newCount) {
967     checkNonnegative(oldCount, "oldCount");
968     checkNonnegative(newCount, "newCount");
969 
970     if (self.count(element) == oldCount) {
971       self.setCount(element, newCount);
972       return true;
973     } else {
974       return false;
975     }
976   }
977 
978   static <E extends @Nullable Object> Iterator<E> elementIterator(
979       Iterator<Entry<E>> entryIterator) {
980     return new TransformedIterator<Entry<E>, E>(entryIterator) {
981       @Override
982       @ParametricNullness
983       E transform(Entry<E> entry) {
984         return entry.getElement();
985       }
986     };
987   }
988 
989   abstract static class ElementSet<E extends @Nullable Object> extends Sets.ImprovedAbstractSet<E> {
990     abstract Multiset<E> multiset();
991 
992     @Override
993     public void clear() {
994       multiset().clear();
995     }
996 
997     @Override
998     public boolean contains(@CheckForNull Object o) {
999       return multiset().contains(o);
1000     }
1001 
1002     @Override
1003     public boolean containsAll(Collection<?> c) {
1004       return multiset().containsAll(c);
1005     }
1006 
1007     @Override
1008     public boolean isEmpty() {
1009       return multiset().isEmpty();
1010     }
1011 
1012     @Override
1013     public abstract Iterator<E> iterator();
1014 
1015     @Override
1016     public boolean remove(@CheckForNull Object o) {
1017       return multiset().remove(o, Integer.MAX_VALUE) > 0;
1018     }
1019 
1020     @Override
1021     public int size() {
1022       return multiset().entrySet().size();
1023     }
1024   }
1025 
1026   abstract static class EntrySet<E extends @Nullable Object>
1027       extends Sets.ImprovedAbstractSet<Entry<E>> {
1028     abstract Multiset<E> multiset();
1029 
1030     @Override
1031     public boolean contains(@CheckForNull Object o) {
1032       if (o instanceof Entry) {
1033         /*
1034          * The GWT compiler wrongly issues a warning here.
1035          */
1036         @SuppressWarnings("cast")
1037         Entry<?> entry = (Entry<?>) o;
1038         if (entry.getCount() <= 0) {
1039           return false;
1040         }
1041         int count = multiset().count(entry.getElement());
1042         return count == entry.getCount();
1043       }
1044       return false;
1045     }
1046 
1047     // GWT compiler warning; see contains().
1048     @SuppressWarnings("cast")
1049     @Override
1050     public boolean remove(@CheckForNull Object object) {
1051       if (object instanceof Multiset.Entry) {
1052         Entry<?> entry = (Entry<?>) object;
1053         Object element = entry.getElement();
1054         int entryCount = entry.getCount();
1055         if (entryCount != 0) {
1056           // Safe as long as we never add a new entry, which we won't.
1057           // (Presumably it can still throw CCE/NPE but only if the underlying Multiset does.)
1058           @SuppressWarnings({"unchecked", "nullness"})
1059           Multiset<@Nullable Object> multiset = (Multiset<@Nullable Object>) multiset();
1060           return multiset.setCount(element, entryCount, 0);
1061         }
1062       }
1063       return false;
1064     }
1065 
1066     @Override
1067     public void clear() {
1068       multiset().clear();
1069     }
1070   }
1071 
1072   /** An implementation of {@link Multiset#iterator}. */
1073   static <E extends @Nullable Object> Iterator<E> iteratorImpl(Multiset<E> multiset) {
1074     return new MultisetIteratorImpl<E>(multiset, multiset.entrySet().iterator());
1075   }
1076 
1077   static final class MultisetIteratorImpl<E extends @Nullable Object> implements Iterator<E> {
1078     private final Multiset<E> multiset;
1079     private final Iterator<Entry<E>> entryIterator;
1080     @CheckForNull private Entry<E> currentEntry;
1081 
1082     /** Count of subsequent elements equal to current element */
1083     private int laterCount;
1084 
1085     /** Count of all elements equal to current element */
1086     private int totalCount;
1087 
1088     private boolean canRemove;
1089 
1090     MultisetIteratorImpl(Multiset<E> multiset, Iterator<Entry<E>> entryIterator) {
1091       this.multiset = multiset;
1092       this.entryIterator = entryIterator;
1093     }
1094 
1095     @Override
1096     public boolean hasNext() {
1097       return laterCount > 0 || entryIterator.hasNext();
1098     }
1099 
1100     @Override
1101     @ParametricNullness
1102     public E next() {
1103       if (!hasNext()) {
1104         throw new NoSuchElementException();
1105       }
1106       if (laterCount == 0) {
1107         currentEntry = entryIterator.next();
1108         totalCount = laterCount = currentEntry.getCount();
1109       }
1110       laterCount--;
1111       canRemove = true;
1112       /*
1113        * requireNonNull is safe because laterCount starts at 0, forcing us to initialize
1114        * currentEntry above. After that, we never clear it.
1115        */
1116       return requireNonNull(currentEntry).getElement();
1117     }
1118 
1119     @Override
1120     public void remove() {
1121       checkRemove(canRemove);
1122       if (totalCount == 1) {
1123         entryIterator.remove();
1124       } else {
1125         /*
1126          * requireNonNull is safe because canRemove is set to true only after we initialize
1127          * currentEntry (which we never subsequently clear).
1128          */
1129         multiset.remove(requireNonNull(currentEntry).getElement());
1130       }
1131       totalCount--;
1132       canRemove = false;
1133     }
1134   }
1135 
1136   static <E extends @Nullable Object> Spliterator<E> spliteratorImpl(Multiset<E> multiset) {
1137     Spliterator<Entry<E>> entrySpliterator = multiset.entrySet().spliterator();
1138     return CollectSpliterators.flatMap(
1139         entrySpliterator,
1140         entry -> Collections.nCopies(entry.getCount(), entry.getElement()).spliterator(),
1141         Spliterator.SIZED
1142             | (entrySpliterator.characteristics()
1143                 & (Spliterator.ORDERED | Spliterator.NONNULL | Spliterator.IMMUTABLE)),
1144         multiset.size());
1145   }
1146 
1147   /** An implementation of {@link Multiset#size}. */
1148   static int linearTimeSizeImpl(Multiset<?> multiset) {
1149     long size = 0;
1150     for (Entry<?> entry : multiset.entrySet()) {
1151       size += entry.getCount();
1152     }
1153     return Ints.saturatedCast(size);
1154   }
1155 
1156   /** Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557 */
1157   static <T extends @Nullable Object> Multiset<T> cast(Iterable<T> iterable) {
1158     return (Multiset<T>) iterable;
1159   }
1160 
1161   /**
1162    * Returns a copy of {@code multiset} as an {@link ImmutableMultiset} whose iteration order puts
1163    * the highest count first, with ties broken by the iteration order of the original multiset.
1164    *
1165    * @since 11.0
1166    */
1167   public static <E> ImmutableMultiset<E> copyHighestCountFirst(Multiset<E> multiset) {
1168     Entry<E>[] entries = (Entry<E>[]) multiset.entrySet().toArray(new Entry[0]);
1169     Arrays.sort(entries, DecreasingCount.INSTANCE);
1170     return ImmutableMultiset.copyFromEntries(Arrays.asList(entries));
1171   }
1172 
1173   private static final class DecreasingCount implements Comparator<Entry<?>> {
1174     static final Comparator<Entry<?>> INSTANCE = new DecreasingCount();
1175 
1176     @Override
1177     public int compare(Entry<?> entry1, Entry<?> entry2) {
1178       return entry2.getCount() - entry1.getCount(); // subtracting two nonnegative integers
1179     }
1180   }
1181 
1182   /**
1183    * An {@link AbstractMultiset} with additional default implementations, some of them linear-time
1184    * implementations in terms of {@code elementSet} and {@code entrySet}.
1185    */
1186   private abstract static class ViewMultiset<E extends @Nullable Object>
1187       extends AbstractMultiset<E> {
1188     @Override
1189     public int size() {
1190       return linearTimeSizeImpl(this);
1191     }
1192 
1193     @Override
1194     public void clear() {
1195       elementSet().clear();
1196     }
1197 
1198     @Override
1199     public Iterator<E> iterator() {
1200       return iteratorImpl(this);
1201     }
1202 
1203     @Override
1204     int distinctElements() {
1205       return elementSet().size();
1206     }
1207   }
1208 }
1209