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