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