001/*
002 * Copyright (C) 2011 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the
010 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
011 * express or implied. See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014
015package com.google.common.collect;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkNotNull;
019
020import com.google.common.annotations.GwtIncompatible;
021import com.google.common.annotations.J2ktIncompatible;
022import com.google.common.annotations.VisibleForTesting;
023import com.google.common.math.IntMath;
024import com.google.errorprone.annotations.CanIgnoreReturnValue;
025import com.google.errorprone.annotations.DoNotCall;
026import com.google.errorprone.annotations.concurrent.LazyInit;
027import java.io.InvalidObjectException;
028import java.io.ObjectInputStream;
029import java.io.Serializable;
030import java.util.Arrays;
031import java.util.Collection;
032import java.util.Collections;
033import java.util.Comparator;
034import java.util.Iterator;
035import java.util.List;
036import java.util.function.Function;
037import java.util.function.ToIntFunction;
038import java.util.stream.Collector;
039import javax.annotation.CheckForNull;
040import org.checkerframework.checker.nullness.qual.Nullable;
041
042/**
043 * A {@link SortedMultiset} whose contents will never change, with many other important properties
044 * detailed at {@link ImmutableCollection}.
045 *
046 * <p><b>Warning:</b> as with any sorted collection, you are strongly advised not to use a {@link
047 * Comparator} or {@link Comparable} type whose comparison behavior is <i>inconsistent with
048 * equals</i>. That is, {@code a.compareTo(b)} or {@code comparator.compare(a, b)} should equal zero
049 * <i>if and only if</i> {@code a.equals(b)}. If this advice is not followed, the resulting
050 * collection will not correctly obey its specification.
051 *
052 * <p>See the Guava User Guide article on <a href=
053 * "https://github.com/google/guava/wiki/ImmutableCollectionsExplained">immutable collections</a>.
054 *
055 * @author Louis Wasserman
056 * @since 12.0
057 */
058@GwtIncompatible // hasn't been tested yet
059public abstract class ImmutableSortedMultiset<E> extends ImmutableMultiset<E>
060    implements SortedMultiset<E> {
061  // TODO(lowasser): GWT compatibility
062
063  /**
064   * Returns a {@code Collector} that accumulates the input elements into a new {@code
065   * ImmutableMultiset}. Elements are sorted by the specified comparator.
066   *
067   * <p><b>Warning:</b> {@code comparator} should be <i>consistent with {@code equals}</i> as
068   * explained in the {@link Comparator} documentation.
069   *
070   * @since 33.2.0 (available since 21.0 in guava-jre)
071   */
072  @SuppressWarnings("Java7ApiChecker")
073  @IgnoreJRERequirement // Users will use this only if they're already using streams.
074  public static <E> Collector<E, ?, ImmutableSortedMultiset<E>> toImmutableSortedMultiset(
075      Comparator<? super E> comparator) {
076    return toImmutableSortedMultiset(comparator, Function.identity(), e -> 1);
077  }
078
079  /**
080   * Returns a {@code Collector} that accumulates elements into an {@code ImmutableSortedMultiset}
081   * whose elements are the result of applying {@code elementFunction} to the inputs, with counts
082   * equal to the result of applying {@code countFunction} to the inputs.
083   *
084   * <p>If the mapped elements contain duplicates (according to {@code comparator}), the first
085   * occurrence in encounter order appears in the resulting multiset, with count equal to the sum of
086   * the outputs of {@code countFunction.applyAsInt(t)} for each {@code t} mapped to that element.
087   *
088   * @since 33.2.0 (available since 22.0 in guava-jre)
089   */
090  @SuppressWarnings("Java7ApiChecker")
091  @IgnoreJRERequirement // Users will use this only if they're already using streams.
092  public static <T extends @Nullable Object, E>
093      Collector<T, ?, ImmutableSortedMultiset<E>> toImmutableSortedMultiset(
094          Comparator<? super E> comparator,
095          Function<? super T, ? extends E> elementFunction,
096          ToIntFunction<? super T> countFunction) {
097    checkNotNull(comparator);
098    checkNotNull(elementFunction);
099    checkNotNull(countFunction);
100    return Collector.of(
101        () -> TreeMultiset.create(comparator),
102        (multiset, t) -> mapAndAdd(t, multiset, elementFunction, countFunction),
103        (multiset1, multiset2) -> {
104          multiset1.addAll(multiset2);
105          return multiset1;
106        },
107        (Multiset<E> multiset) -> copyOfSortedEntries(comparator, multiset.entrySet()));
108  }
109
110  @SuppressWarnings("Java7ApiChecker")
111  @IgnoreJRERequirement // helper for toImmutableSortedMultiset
112  /*
113   * If we make these calls inline inside toImmutableSortedMultiset, we get an Animal Sniffer error,
114   * despite the @IgnoreJRERequirement annotation there. My assumption is that, because javac
115   * generates a synthetic method for the body of the lambda, the actual method calls that Animal
116   * Sniffer is flagging don't appear inside toImmutableSortedMultiset but rather inside that
117   * synthetic method. By moving those calls to a named method, we're able to apply
118   * @IgnoreJRERequirement somewhere that it will help.
119   */
120  private static <T extends @Nullable Object, E> void mapAndAdd(
121      T t,
122      Multiset<E> multiset,
123      Function<? super T, ? extends E> elementFunction,
124      ToIntFunction<? super T> countFunction) {
125    multiset.add(checkNotNull(elementFunction.apply(t)), countFunction.applyAsInt(t));
126  }
127
128  /**
129   * Returns the empty immutable sorted multiset.
130   *
131   * <p><b>Performance note:</b> the instance returned is a singleton.
132   */
133  @SuppressWarnings("unchecked")
134  public static <E> ImmutableSortedMultiset<E> of() {
135    return (ImmutableSortedMultiset) RegularImmutableSortedMultiset.NATURAL_EMPTY_MULTISET;
136  }
137
138  /** Returns an immutable sorted multiset containing a single element. */
139  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(E e1) {
140    RegularImmutableSortedSet<E> elementSet =
141        (RegularImmutableSortedSet<E>) ImmutableSortedSet.of(e1);
142    long[] cumulativeCounts = {0, 1};
143    return new RegularImmutableSortedMultiset<>(elementSet, cumulativeCounts, 0, 1);
144  }
145
146  /**
147   * Returns an immutable sorted multiset containing the given elements sorted by their natural
148   * ordering.
149   *
150   * @throws NullPointerException if any element is null
151   */
152  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(E e1, E e2) {
153    return copyOf(Ordering.natural(), Arrays.asList(e1, e2));
154  }
155
156  /**
157   * Returns an immutable sorted multiset containing the given elements sorted by their natural
158   * ordering.
159   *
160   * @throws NullPointerException if any element is null
161   */
162  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(E e1, E e2, E e3) {
163    return copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3));
164  }
165
166  /**
167   * Returns an immutable sorted multiset containing the given elements sorted by their natural
168   * ordering.
169   *
170   * @throws NullPointerException if any element is null
171   */
172  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(
173      E e1, E e2, E e3, E e4) {
174    return copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3, e4));
175  }
176
177  /**
178   * Returns an immutable sorted multiset containing the given elements sorted by their natural
179   * ordering.
180   *
181   * @throws NullPointerException if any element is null
182   */
183  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(
184      E e1, E e2, E e3, E e4, E e5) {
185    return copyOf(Ordering.natural(), Arrays.asList(e1, e2, e3, e4, e5));
186  }
187
188  /**
189   * Returns an immutable sorted multiset containing the given elements sorted by their natural
190   * ordering.
191   *
192   * @throws NullPointerException if any element is null
193   */
194  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> of(
195      E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
196    int size = remaining.length + 6;
197    List<E> all = Lists.newArrayListWithCapacity(size);
198    Collections.addAll(all, e1, e2, e3, e4, e5, e6);
199    Collections.addAll(all, remaining);
200    return copyOf(Ordering.natural(), all);
201  }
202
203  /**
204   * Returns an immutable sorted multiset containing the given elements sorted by their natural
205   * ordering.
206   *
207   * @throws NullPointerException if any of {@code elements} is null
208   */
209  public static <E extends Comparable<? super E>> ImmutableSortedMultiset<E> copyOf(E[] elements) {
210    return copyOf(Ordering.natural(), Arrays.asList(elements));
211  }
212
213  /**
214   * Returns an immutable sorted multiset containing the given elements sorted by their natural
215   * ordering. To create a copy of a {@code SortedMultiset} that preserves the comparator, call
216   * {@link #copyOfSorted} instead. This method iterates over {@code elements} at most once.
217   *
218   * <p>Note that if {@code s} is a {@code Multiset<String>}, then {@code
219   * ImmutableSortedMultiset.copyOf(s)} returns an {@code ImmutableSortedMultiset<String>}
220   * containing each of the strings in {@code s}, while {@code ImmutableSortedMultiset.of(s)}
221   * returns an {@code ImmutableSortedMultiset<Multiset<String>>} containing one element (the given
222   * multiset itself).
223   *
224   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
225   * safe to do so. The exact circumstances under which a copy will or will not be performed are
226   * undocumented and subject to change.
227   *
228   * <p>This method is not type-safe, as it may be called on elements that are not mutually
229   * comparable.
230   *
231   * @throws ClassCastException if the elements are not mutually comparable
232   * @throws NullPointerException if any of {@code elements} is null
233   */
234  public static <E> ImmutableSortedMultiset<E> copyOf(Iterable<? extends E> elements) {
235    // Hack around E not being a subtype of Comparable.
236    // Unsafe, see ImmutableSortedMultisetFauxverideShim.
237    @SuppressWarnings("unchecked")
238    Ordering<E> naturalOrder = (Ordering<E>) Ordering.<Comparable<?>>natural();
239    return copyOf(naturalOrder, elements);
240  }
241
242  /**
243   * Returns an immutable sorted multiset containing the given elements sorted by their natural
244   * ordering.
245   *
246   * <p>This method is not type-safe, as it may be called on elements that are not mutually
247   * comparable.
248   *
249   * @throws ClassCastException if the elements are not mutually comparable
250   * @throws NullPointerException if any of {@code elements} is null
251   */
252  public static <E> ImmutableSortedMultiset<E> copyOf(Iterator<? extends E> elements) {
253    // Hack around E not being a subtype of Comparable.
254    // Unsafe, see ImmutableSortedMultisetFauxverideShim.
255    @SuppressWarnings("unchecked")
256    Ordering<E> naturalOrder = (Ordering<E>) Ordering.<Comparable<?>>natural();
257    return copyOf(naturalOrder, elements);
258  }
259
260  /**
261   * Returns an immutable sorted multiset containing the given elements sorted by the given {@code
262   * Comparator}.
263   *
264   * @throws NullPointerException if {@code comparator} or any of {@code elements} is null
265   */
266  public static <E> ImmutableSortedMultiset<E> copyOf(
267      Comparator<? super E> comparator, Iterator<? extends E> elements) {
268    checkNotNull(comparator);
269    return new Builder<E>(comparator).addAll(elements).build();
270  }
271
272  /**
273   * Returns an immutable sorted multiset containing the given elements sorted by the given {@code
274   * Comparator}. This method iterates over {@code elements} at most once.
275   *
276   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
277   * safe to do so. The exact circumstances under which a copy will or will not be performed are
278   * undocumented and subject to change.
279   *
280   * @throws NullPointerException if {@code comparator} or any of {@code elements} is null
281   */
282  public static <E> ImmutableSortedMultiset<E> copyOf(
283      Comparator<? super E> comparator, Iterable<? extends E> elements) {
284    if (elements instanceof ImmutableSortedMultiset) {
285      @SuppressWarnings("unchecked") // immutable collections are always safe for covariant casts
286      ImmutableSortedMultiset<E> multiset = (ImmutableSortedMultiset<E>) elements;
287      if (comparator.equals(multiset.comparator())) {
288        if (multiset.isPartialView()) {
289          return copyOfSortedEntries(comparator, multiset.entrySet().asList());
290        } else {
291          return multiset;
292        }
293      }
294    }
295    return new ImmutableSortedMultiset.Builder<E>(comparator).addAll(elements).build();
296  }
297
298  /**
299   * Returns an immutable sorted multiset containing the elements of a sorted multiset, sorted by
300   * the same {@code Comparator}. That behavior differs from {@link #copyOf(Iterable)}, which always
301   * uses the natural ordering of the elements.
302   *
303   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
304   * safe to do so. The exact circumstances under which a copy will or will not be performed are
305   * undocumented and subject to change.
306   *
307   * <p>This method is safe to use even when {@code sortedMultiset} is a synchronized or concurrent
308   * collection that is currently being modified by another thread.
309   *
310   * @throws NullPointerException if {@code sortedMultiset} or any of its elements is null
311   */
312  public static <E> ImmutableSortedMultiset<E> copyOfSorted(SortedMultiset<E> sortedMultiset) {
313    return copyOfSortedEntries(
314        sortedMultiset.comparator(), Lists.newArrayList(sortedMultiset.entrySet()));
315  }
316
317  private static <E> ImmutableSortedMultiset<E> copyOfSortedEntries(
318      Comparator<? super E> comparator, Collection<Entry<E>> entries) {
319    if (entries.isEmpty()) {
320      return emptyMultiset(comparator);
321    }
322    ImmutableList.Builder<E> elementsBuilder = new ImmutableList.Builder<>(entries.size());
323    long[] cumulativeCounts = new long[entries.size() + 1];
324    int i = 0;
325    for (Entry<E> entry : entries) {
326      elementsBuilder.add(entry.getElement());
327      cumulativeCounts[i + 1] = cumulativeCounts[i] + entry.getCount();
328      i++;
329    }
330    return new RegularImmutableSortedMultiset<>(
331        new RegularImmutableSortedSet<E>(elementsBuilder.build(), comparator),
332        cumulativeCounts,
333        0,
334        entries.size());
335  }
336
337  @SuppressWarnings("unchecked")
338  static <E> ImmutableSortedMultiset<E> emptyMultiset(Comparator<? super E> comparator) {
339    if (Ordering.natural().equals(comparator)) {
340      return (ImmutableSortedMultiset<E>) RegularImmutableSortedMultiset.NATURAL_EMPTY_MULTISET;
341    } else {
342      return new RegularImmutableSortedMultiset<>(comparator);
343    }
344  }
345
346  ImmutableSortedMultiset() {}
347
348  @Override
349  public final Comparator<? super E> comparator() {
350    return elementSet().comparator();
351  }
352
353  @Override
354  public abstract ImmutableSortedSet<E> elementSet();
355
356  @LazyInit @CheckForNull transient ImmutableSortedMultiset<E> descendingMultiset;
357
358  @Override
359  public ImmutableSortedMultiset<E> descendingMultiset() {
360    ImmutableSortedMultiset<E> result = descendingMultiset;
361    if (result == null) {
362      return descendingMultiset =
363          this.isEmpty()
364              ? emptyMultiset(Ordering.from(comparator()).reverse())
365              : new DescendingImmutableSortedMultiset<E>(this);
366    }
367    return result;
368  }
369
370  /**
371   * {@inheritDoc}
372   *
373   * <p>This implementation is guaranteed to throw an {@link UnsupportedOperationException}.
374   *
375   * @throws UnsupportedOperationException always
376   * @deprecated Unsupported operation.
377   */
378  @CanIgnoreReturnValue
379  @Deprecated
380  @Override
381  @DoNotCall("Always throws UnsupportedOperationException")
382  @CheckForNull
383  public final Entry<E> pollFirstEntry() {
384    throw new UnsupportedOperationException();
385  }
386
387  /**
388   * {@inheritDoc}
389   *
390   * <p>This implementation is guaranteed to throw an {@link UnsupportedOperationException}.
391   *
392   * @throws UnsupportedOperationException always
393   * @deprecated Unsupported operation.
394   */
395  @CanIgnoreReturnValue
396  @Deprecated
397  @Override
398  @DoNotCall("Always throws UnsupportedOperationException")
399  @CheckForNull
400  public final Entry<E> pollLastEntry() {
401    throw new UnsupportedOperationException();
402  }
403
404  @Override
405  public abstract ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType);
406
407  @Override
408  public ImmutableSortedMultiset<E> subMultiset(
409      E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) {
410    checkArgument(
411        comparator().compare(lowerBound, upperBound) <= 0,
412        "Expected lowerBound <= upperBound but %s > %s",
413        lowerBound,
414        upperBound);
415    return tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType);
416  }
417
418  @Override
419  public abstract ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType);
420
421  /**
422   * Returns a builder that creates immutable sorted multisets with an explicit comparator. If the
423   * comparator has a more general type than the set being generated, such as creating a {@code
424   * SortedMultiset<Integer>} with a {@code Comparator<Number>}, use the {@link Builder} constructor
425   * instead.
426   *
427   * @throws NullPointerException if {@code comparator} is null
428   */
429  public static <E> Builder<E> orderedBy(Comparator<E> comparator) {
430    return new Builder<>(comparator);
431  }
432
433  /**
434   * Returns a builder that creates immutable sorted multisets whose elements are ordered by the
435   * reverse of their natural ordering.
436   *
437   * <p>Note: the type parameter {@code E} extends {@code Comparable<?>} rather than {@code
438   * Comparable<? super E>} in order to accommodate users of obsolete javac versions affected by <a
439   * href="https://bugs.openjdk.org/browse/JDK-6468354">JDK-6468354</a>.
440   */
441  public static <E extends Comparable<?>> Builder<E> reverseOrder() {
442    return new Builder<>(Ordering.<E>natural().reverse());
443  }
444
445  /**
446   * Returns a builder that creates immutable sorted multisets whose elements are ordered by their
447   * natural ordering. The sorted multisets use {@link Ordering#natural()} as the comparator. This
448   * method provides more type-safety than {@link #builder}, as it can be called only for classes
449   * that implement {@link Comparable}.
450   *
451   * <p>Note: the type parameter {@code E} extends {@code Comparable<?>} rather than {@code
452   * Comparable<? super E>} in order to accommodate users of obsolete javac versions affected by <a
453   * href="https://bugs.openjdk.org/browse/JDK-6468354">JDK-6468354</a>.
454   */
455  public static <E extends Comparable<?>> Builder<E> naturalOrder() {
456    return new Builder<>(Ordering.natural());
457  }
458
459  /**
460   * A builder for creating immutable multiset instances, especially {@code public static final}
461   * multisets ("constant multisets"). Example:
462   *
463   * <pre>{@code
464   * public static final ImmutableSortedMultiset<Bean> BEANS =
465   *     new ImmutableSortedMultiset.Builder<Bean>(colorComparator())
466   *         .addCopies(Bean.COCOA, 4)
467   *         .addCopies(Bean.GARDEN, 6)
468   *         .addCopies(Bean.RED, 8)
469   *         .addCopies(Bean.BLACK_EYED, 10)
470   *         .build();
471   * }</pre>
472   *
473   * <p>Builder instances can be reused; it is safe to call {@link #build} multiple times to build
474   * multiple multisets in series.
475   *
476   * @since 12.0
477   */
478  public static class Builder<E> extends ImmutableMultiset.Builder<E> {
479    /*
480     * We keep an array of elements and counts.  Periodically -- when we need more room in the
481     * array, or when we're building, or the like -- we sort, deduplicate, and combine the counts.
482     * Negative counts indicate a setCount operation with ~counts[i].
483     */
484
485    private final Comparator<? super E> comparator;
486
487    @VisibleForTesting E[] elements;
488    private int[] counts;
489
490    /*
491     * The number of used positions in the elements array.  We deduplicate periodically, so this
492     * may fluctuate up and down.
493     */
494    private int length;
495
496    // True if we just called build() and the elements array is being used by a created ISM, meaning
497    // we shouldn't modify that array further.
498    private boolean forceCopyElements;
499
500    /**
501     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
502     * ImmutableSortedMultiset#orderedBy(Comparator)}.
503     */
504    @SuppressWarnings("unchecked")
505    public Builder(Comparator<? super E> comparator) {
506      super(true); // doesn't allocate hash table in supertype
507      this.comparator = checkNotNull(comparator);
508      this.elements = (E[]) new Object[ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY];
509      this.counts = new int[ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY];
510    }
511
512    /** Check if we need to do deduplication and coalescing, and if so, do it. */
513    private void maintenance() {
514      if (length == elements.length) {
515        dedupAndCoalesce(true);
516      } else if (forceCopyElements) {
517        this.elements = Arrays.copyOf(elements, elements.length);
518        // we don't currently need to copy the counts array, because we don't use it directly
519        // in built ISMs
520      }
521      forceCopyElements = false;
522    }
523
524    private void dedupAndCoalesce(boolean maybeExpand) {
525      if (length == 0) {
526        return;
527      }
528      E[] sortedElements = Arrays.copyOf(elements, length);
529      Arrays.sort(sortedElements, comparator);
530      int uniques = 1;
531      for (int i = 1; i < sortedElements.length; i++) {
532        if (comparator.compare(sortedElements[uniques - 1], sortedElements[i]) < 0) {
533          sortedElements[uniques] = sortedElements[i];
534          uniques++;
535        }
536      }
537      Arrays.fill(sortedElements, uniques, length, null);
538      if (maybeExpand && uniques * 4 > length * 3) {
539        // lots of nonduplicated elements, expand the array by 50%
540        sortedElements =
541            Arrays.copyOf(sortedElements, IntMath.saturatedAdd(length, length / 2 + 1));
542      }
543      int[] sortedCounts = new int[sortedElements.length];
544      for (int i = 0; i < length; i++) {
545        int index = Arrays.binarySearch(sortedElements, 0, uniques, elements[i], comparator);
546        if (counts[i] >= 0) {
547          sortedCounts[index] += counts[i];
548        } else {
549          sortedCounts[index] = ~counts[i];
550        }
551      }
552      // Note that we're not getting rid, yet, of elements with count 0.  We'll do that in build().
553      this.elements = sortedElements;
554      this.counts = sortedCounts;
555      this.length = uniques;
556    }
557
558    /**
559     * Adds {@code element} to the {@code ImmutableSortedMultiset}.
560     *
561     * @param element the element to add
562     * @return this {@code Builder} object
563     * @throws NullPointerException if {@code element} is null
564     */
565    @CanIgnoreReturnValue
566    @Override
567    public Builder<E> add(E element) {
568      return addCopies(element, 1);
569    }
570
571    /**
572     * Adds each element of {@code elements} to the {@code ImmutableSortedMultiset}.
573     *
574     * @param elements the elements to add
575     * @return this {@code Builder} object
576     * @throws NullPointerException if {@code elements} is null or contains a null element
577     */
578    @CanIgnoreReturnValue
579    @Override
580    public Builder<E> add(E... elements) {
581      for (E element : elements) {
582        add(element);
583      }
584      return this;
585    }
586
587    /**
588     * Adds a number of occurrences of an element to this {@code ImmutableSortedMultiset}.
589     *
590     * @param element the element to add
591     * @param occurrences the number of occurrences of the element to add. May be zero, in which
592     *     case no change will be made.
593     * @return this {@code Builder} object
594     * @throws NullPointerException if {@code element} is null
595     * @throws IllegalArgumentException if {@code occurrences} is negative, or if this operation
596     *     would result in more than {@link Integer#MAX_VALUE} occurrences of the element
597     */
598    @CanIgnoreReturnValue
599    @Override
600    public Builder<E> addCopies(E element, int occurrences) {
601      checkNotNull(element);
602      CollectPreconditions.checkNonnegative(occurrences, "occurrences");
603      if (occurrences == 0) {
604        return this;
605      }
606      maintenance();
607      elements[length] = element;
608      counts[length] = occurrences;
609      length++;
610      return this;
611    }
612
613    /**
614     * Adds or removes the necessary occurrences of an element such that the element attains the
615     * desired count.
616     *
617     * @param element the element to add or remove occurrences of
618     * @param count the desired count of the element in this multiset
619     * @return this {@code Builder} object
620     * @throws NullPointerException if {@code element} is null
621     * @throws IllegalArgumentException if {@code count} is negative
622     */
623    @CanIgnoreReturnValue
624    @Override
625    public Builder<E> setCount(E element, int count) {
626      checkNotNull(element);
627      CollectPreconditions.checkNonnegative(count, "count");
628      maintenance();
629      elements[length] = element;
630      counts[length] = ~count;
631      length++;
632      return this;
633    }
634
635    /**
636     * Adds each element of {@code elements} to the {@code ImmutableSortedMultiset}.
637     *
638     * @param elements the {@code Iterable} to add to the {@code ImmutableSortedMultiset}
639     * @return this {@code Builder} object
640     * @throws NullPointerException if {@code elements} is null or contains a null element
641     */
642    @CanIgnoreReturnValue
643    @Override
644    public Builder<E> addAll(Iterable<? extends E> elements) {
645      if (elements instanceof Multiset) {
646        for (Entry<? extends E> entry : ((Multiset<? extends E>) elements).entrySet()) {
647          addCopies(entry.getElement(), entry.getCount());
648        }
649      } else {
650        for (E e : elements) {
651          add(e);
652        }
653      }
654      return this;
655    }
656
657    /**
658     * Adds each element of {@code elements} to the {@code ImmutableSortedMultiset}.
659     *
660     * @param elements the elements to add to the {@code ImmutableSortedMultiset}
661     * @return this {@code Builder} object
662     * @throws NullPointerException if {@code elements} is null or contains a null element
663     */
664    @CanIgnoreReturnValue
665    @Override
666    public Builder<E> addAll(Iterator<? extends E> elements) {
667      while (elements.hasNext()) {
668        add(elements.next());
669      }
670      return this;
671    }
672
673    private void dedupAndCoalesceAndDeleteEmpty() {
674      dedupAndCoalesce(false);
675
676      // If there was a setCount(elem, 0), those elements are still present.  Eliminate them.
677      int size = 0;
678      for (int i = 0; i < length; i++) {
679        if (counts[i] > 0) {
680          elements[size] = elements[i];
681          counts[size] = counts[i];
682          size++;
683        }
684      }
685      Arrays.fill(elements, size, length, null);
686      Arrays.fill(counts, size, length, 0);
687      length = size;
688    }
689
690    /**
691     * Returns a newly-created {@code ImmutableSortedMultiset} based on the contents of the {@code
692     * Builder}.
693     */
694    @Override
695    public ImmutableSortedMultiset<E> build() {
696      dedupAndCoalesceAndDeleteEmpty();
697      if (length == 0) {
698        return emptyMultiset(comparator);
699      }
700      RegularImmutableSortedSet<E> elementSet =
701          (RegularImmutableSortedSet<E>) ImmutableSortedSet.construct(comparator, length, elements);
702      long[] cumulativeCounts = new long[length + 1];
703      for (int i = 0; i < length; i++) {
704        cumulativeCounts[i + 1] = cumulativeCounts[i] + counts[i];
705      }
706      forceCopyElements = true;
707      return new RegularImmutableSortedMultiset<E>(elementSet, cumulativeCounts, 0, length);
708    }
709  }
710
711  @J2ktIncompatible // serialization
712  private static final class SerializedForm<E> implements Serializable {
713    final Comparator<? super E> comparator;
714    final E[] elements;
715    final int[] counts;
716
717    @SuppressWarnings("unchecked")
718    SerializedForm(SortedMultiset<E> multiset) {
719      this.comparator = multiset.comparator();
720      int n = multiset.entrySet().size();
721      elements = (E[]) new Object[n];
722      counts = new int[n];
723      int i = 0;
724      for (Entry<E> entry : multiset.entrySet()) {
725        elements[i] = entry.getElement();
726        counts[i] = entry.getCount();
727        i++;
728      }
729    }
730
731    Object readResolve() {
732      int n = elements.length;
733      Builder<E> builder = new Builder<>(comparator);
734      for (int i = 0; i < n; i++) {
735        builder.addCopies(elements[i], counts[i]);
736      }
737      return builder.build();
738    }
739  }
740
741  @Override
742  @J2ktIncompatible // serialization
743  Object writeReplace() {
744    return new SerializedForm<E>(this);
745  }
746
747  @J2ktIncompatible // java.io.ObjectInputStream
748  private void readObject(ObjectInputStream stream) throws InvalidObjectException {
749    throw new InvalidObjectException("Use SerializedForm");
750  }
751
752  /**
753   * Not supported. Use {@link #toImmutableSortedMultiset} instead. This method exists only to hide
754   * {@link ImmutableMultiset#toImmutableMultiset} from consumers of {@code
755   * ImmutableSortedMultiset}.
756   *
757   * @throws UnsupportedOperationException always
758   * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}.
759   * @since 33.2.0 (available since 21.0 in guava-jre)
760   */
761  @DoNotCall("Use toImmutableSortedMultiset.")
762  @Deprecated
763  @SuppressWarnings("Java7ApiChecker")
764  @IgnoreJRERequirement // Users will use this only if they're already using streams.
765  public static <E> Collector<E, ?, ImmutableMultiset<E>> toImmutableMultiset() {
766    throw new UnsupportedOperationException();
767  }
768
769  /**
770   * Not supported. Use {@link #toImmutableSortedMultiset} instead. This method exists only to hide
771   * {@link ImmutableMultiset#toImmutableMultiset} from consumers of {@code
772   * ImmutableSortedMultiset}.
773   *
774   * @throws UnsupportedOperationException always
775   * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}.
776   * @since 33.2.0 (available since 22.0 in guava-jre)
777   */
778  @DoNotCall("Use toImmutableSortedMultiset.")
779  @Deprecated
780  @SuppressWarnings("Java7ApiChecker")
781  @IgnoreJRERequirement // Users will use this only if they're already using streams.
782  public static <T extends @Nullable Object, E>
783      Collector<T, ?, ImmutableMultiset<E>> toImmutableMultiset(
784          Function<? super T, ? extends E> elementFunction,
785          ToIntFunction<? super T> countFunction) {
786    throw new UnsupportedOperationException();
787  }
788
789  /**
790   * Not supported. Use {@link #naturalOrder}, which offers better type-safety, instead. This method
791   * exists only to hide {@link ImmutableMultiset#builder} from consumers of {@code
792   * ImmutableSortedMultiset}.
793   *
794   * @throws UnsupportedOperationException always
795   * @deprecated Use {@link ImmutableSortedMultiset#naturalOrder}, which offers better type-safety.
796   */
797  @DoNotCall("Use naturalOrder.")
798  @Deprecated
799  public static <E> ImmutableSortedMultiset.Builder<E> builder() {
800    throw new UnsupportedOperationException();
801  }
802
803  /**
804   * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code
805   * Comparable} element.</b> Proper calls will resolve to the version in {@code
806   * ImmutableSortedMultiset}, not this dummy version.
807   *
808   * @throws UnsupportedOperationException always
809   * @deprecated <b>Pass a parameter of type {@code Comparable} to use {@link
810   *     ImmutableSortedMultiset#of(Comparable)}.</b>
811   */
812  @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)")
813  @Deprecated
814  public static <E> ImmutableSortedMultiset<E> of(E e1) {
815    throw new UnsupportedOperationException();
816  }
817
818  /**
819   * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code
820   * Comparable} element.</b> Proper calls will resolve to the version in {@code
821   * ImmutableSortedMultiset}, not this dummy version.
822   *
823   * @throws UnsupportedOperationException always
824   * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
825   *     ImmutableSortedMultiset#of(Comparable, Comparable)}.</b>
826   */
827  @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)")
828  @Deprecated
829  public static <E> ImmutableSortedMultiset<E> of(E e1, E e2) {
830    throw new UnsupportedOperationException();
831  }
832
833  /**
834   * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code
835   * Comparable} element.</b> Proper calls will resolve to the version in {@code
836   * ImmutableSortedMultiset}, not this dummy version.
837   *
838   * @throws UnsupportedOperationException always
839   * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
840   *     ImmutableSortedMultiset#of(Comparable, Comparable, Comparable)}.</b>
841   */
842  @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)")
843  @Deprecated
844  public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3) {
845    throw new UnsupportedOperationException();
846  }
847
848  /**
849   * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code
850   * Comparable} element.</b> Proper calls will resolve to the version in {@code
851   * ImmutableSortedMultiset}, not this dummy version.
852   *
853   * @throws UnsupportedOperationException always
854   * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
855   *     ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable)}. </b>
856   */
857  @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)")
858  @Deprecated
859  public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3, E e4) {
860    throw new UnsupportedOperationException();
861  }
862
863  /**
864   * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code
865   * Comparable} element.</b> Proper calls will resolve to the version in {@code
866   * ImmutableSortedMultiset}, not this dummy version.
867   *
868   * @throws UnsupportedOperationException always
869   * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
870   *     ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable, Comparable)} .
871   *     </b>
872   */
873  @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)")
874  @Deprecated
875  public static <E> ImmutableSortedMultiset<E> of(E e1, E e2, E e3, E e4, E e5) {
876    throw new UnsupportedOperationException();
877  }
878
879  /**
880   * Not supported. <b>You are attempting to create a multiset that may contain a non-{@code
881   * Comparable} element.</b> Proper calls will resolve to the version in {@code
882   * ImmutableSortedMultiset}, not this dummy version.
883   *
884   * @throws UnsupportedOperationException always
885   * @deprecated <b>Pass the parameters of type {@code Comparable} to use {@link
886   *     ImmutableSortedMultiset#of(Comparable, Comparable, Comparable, Comparable, Comparable,
887   *     Comparable, Comparable...)} . </b>
888   */
889  @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)")
890  @Deprecated
891  public static <E> ImmutableSortedMultiset<E> of(
892      E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) {
893    throw new UnsupportedOperationException();
894  }
895
896  /**
897   * Not supported. <b>You are attempting to create a multiset that may contain non-{@code
898   * Comparable} elements.</b> Proper calls will resolve to the version in {@code
899   * ImmutableSortedMultiset}, not this dummy version.
900   *
901   * @throws UnsupportedOperationException always
902   * @deprecated <b>Pass parameters of type {@code Comparable} to use {@link
903   *     ImmutableSortedMultiset#copyOf(Comparable[])}.</b>
904   */
905  @DoNotCall("Elements must be Comparable. (Or, pass a Comparator to orderedBy or copyOf.)")
906  @Deprecated
907  // The usage of "Z" here works around bugs in Javadoc (JDK-8318093) and JDiff.
908  public static <Z> ImmutableSortedMultiset<Z> copyOf(Z[] elements) {
909    throw new UnsupportedOperationException();
910  }
911
912  private static final long serialVersionUID = 0xdecaf;
913}