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