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