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.base.Preconditions.checkState;
022import static com.google.common.collect.CollectPreconditions.checkNonnegative;
023import static com.google.common.collect.NullnessCasts.uncheckedCastNullableTToT;
024import static java.lang.Math.max;
025import static java.util.Objects.requireNonNull;
026
027import com.google.common.annotations.GwtCompatible;
028import com.google.common.annotations.GwtIncompatible;
029import com.google.common.annotations.J2ktIncompatible;
030import com.google.common.base.MoreObjects;
031import com.google.common.primitives.Ints;
032import com.google.errorprone.annotations.CanIgnoreReturnValue;
033import java.io.IOException;
034import java.io.ObjectInputStream;
035import java.io.ObjectOutputStream;
036import java.io.Serializable;
037import java.util.Comparator;
038import java.util.ConcurrentModificationException;
039import java.util.Iterator;
040import java.util.NoSuchElementException;
041import java.util.function.ObjIntConsumer;
042import org.jspecify.annotations.Nullable;
043
044/**
045 * A multiset which maintains the ordering of its elements, according to either their natural order
046 * or an explicit {@link Comparator}. In all cases, this implementation uses {@link
047 * Comparable#compareTo} or {@link Comparator#compare} instead of {@link Object#equals} to determine
048 * equivalence of instances.
049 *
050 * <p><b>Warning:</b> The comparison must be <i>consistent with equals</i> as explained by the
051 * {@link Comparable} class specification. Otherwise, the resulting multiset will violate the {@link
052 * java.util.Collection} contract, which is specified in terms of {@link Object#equals}.
053 *
054 * <p>See the Guava User Guide article on <a href=
055 * "https://github.com/google/guava/wiki/NewCollectionTypesExplained#multiset">{@code Multiset}</a>.
056 *
057 * @author Louis Wasserman
058 * @author Jared Levy
059 * @since 2.0
060 */
061@GwtCompatible
062public final class TreeMultiset<E extends @Nullable Object> extends AbstractSortedMultiset<E>
063    implements Serializable {
064
065  /**
066   * Creates a new, empty multiset, sorted according to the elements' natural order. All elements
067   * inserted into the multiset must implement the {@code Comparable} interface. Furthermore, all
068   * such elements must be <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a
069   * {@code ClassCastException} for any elements {@code e1} and {@code e2} in the multiset. If the
070   * user attempts to add an element to the multiset that violates this constraint (for example, the
071   * user attempts to add a string element to a set whose elements are integers), the {@code
072   * add(Object)} call will throw a {@code ClassCastException}.
073   *
074   * <p>The type specification is {@code <E extends Comparable>}, instead of the more specific
075   * {@code <E extends Comparable<? super E>>}, to support classes defined without generics.
076   */
077  @SuppressWarnings("rawtypes") // https://github.com/google/guava/issues/989
078  public static <E extends Comparable> TreeMultiset<E> create() {
079    return new TreeMultiset<>(Ordering.natural());
080  }
081
082  /**
083   * Creates a new, empty multiset, sorted according to the specified comparator. All elements
084   * inserted into the multiset must be <i>mutually comparable</i> by the specified comparator:
085   * {@code comparator.compare(e1, e2)} must not throw a {@code ClassCastException} for any elements
086   * {@code e1} and {@code e2} in the multiset. If the user attempts to add an element to the
087   * multiset that violates this constraint, the {@code add(Object)} call will throw a {@code
088   * ClassCastException}.
089   *
090   * @param comparator the comparator that will be used to sort this multiset. A null value
091   *     indicates that the elements' <i>natural ordering</i> should be used.
092   */
093  @SuppressWarnings("unchecked")
094  public static <E extends @Nullable Object> TreeMultiset<E> create(
095      @Nullable Comparator<? super E> comparator) {
096    return (comparator == null)
097        ? new TreeMultiset<E>((Comparator) Ordering.natural())
098        : new TreeMultiset<E>(comparator);
099  }
100
101  /**
102   * Creates an empty multiset containing the given initial elements, sorted according to the
103   * elements' natural order.
104   *
105   * <p>This implementation is highly efficient when {@code elements} is itself a {@link Multiset}.
106   *
107   * <p>The type specification is {@code <E extends Comparable>}, instead of the more specific
108   * {@code <E extends Comparable<? super E>>}, to support classes defined without generics.
109   */
110  @SuppressWarnings("rawtypes") // https://github.com/google/guava/issues/989
111  public static <E extends Comparable> TreeMultiset<E> create(Iterable<? extends E> elements) {
112    TreeMultiset<E> multiset = create();
113    Iterables.addAll(multiset, elements);
114    return multiset;
115  }
116
117  private final transient Reference<AvlNode<E>> rootReference;
118  private final transient GeneralRange<E> range;
119  private final transient AvlNode<E> header;
120
121  /**
122   * An instance created in {@link #readObject} to be returned from {@link #readResolve}. This field
123   * is used only by those methods, and it is never set in a "normal" instance.
124   *
125   * <p>For more background, see {@code ConcurrentHashMultiset.deserializationReplacement}.
126   */
127  private transient @Nullable TreeMultiset<E> deserializationReplacement;
128
129  private TreeMultiset(
130      Reference<AvlNode<E>> rootReference, GeneralRange<E> range, AvlNode<E> endLink) {
131    super(range.comparator());
132    this.rootReference = rootReference;
133    this.range = range;
134    this.header = endLink;
135  }
136
137  private TreeMultiset(Comparator<? super E> comparator) {
138    super(comparator);
139    this.range = GeneralRange.all(comparator);
140    this.header = new AvlNode<>();
141    successor(header, header);
142    this.rootReference = new Reference<>();
143  }
144
145  /** A function which can be summed across a subtree. */
146  private enum Aggregate {
147    SIZE {
148      @Override
149      int nodeAggregate(AvlNode<?> node) {
150        return node.elemCount;
151      }
152
153      @Override
154      long treeAggregate(@Nullable AvlNode<?> root) {
155        return (root == null) ? 0 : root.totalCount;
156      }
157    },
158    DISTINCT {
159      @Override
160      int nodeAggregate(AvlNode<?> node) {
161        return 1;
162      }
163
164      @Override
165      long treeAggregate(@Nullable AvlNode<?> root) {
166        return (root == null) ? 0 : root.distinctElements;
167      }
168    };
169
170    abstract int nodeAggregate(AvlNode<?> node);
171
172    abstract long treeAggregate(@Nullable AvlNode<?> root);
173  }
174
175  private long aggregateForEntries(Aggregate aggr) {
176    AvlNode<E> root = rootReference.get();
177    long total = aggr.treeAggregate(root);
178    if (range.hasLowerBound()) {
179      total -= aggregateBelowRange(aggr, root);
180    }
181    if (range.hasUpperBound()) {
182      total -= aggregateAboveRange(aggr, root);
183    }
184    return total;
185  }
186
187  private long aggregateBelowRange(Aggregate aggr, @Nullable AvlNode<E> node) {
188    if (node == null) {
189      return 0;
190    }
191    // The cast is safe because we call this method only if hasLowerBound().
192    int cmp =
193        comparator()
194            .compare(uncheckedCastNullableTToT(range.getLowerEndpoint()), node.getElement());
195    if (cmp < 0) {
196      return aggregateBelowRange(aggr, node.left);
197    } else if (cmp == 0) {
198      switch (range.getLowerBoundType()) {
199        case OPEN:
200          return aggr.nodeAggregate(node) + aggr.treeAggregate(node.left);
201        case CLOSED:
202          return aggr.treeAggregate(node.left);
203      }
204      throw new AssertionError();
205    } else {
206      return aggr.treeAggregate(node.left)
207          + aggr.nodeAggregate(node)
208          + aggregateBelowRange(aggr, node.right);
209    }
210  }
211
212  private long aggregateAboveRange(Aggregate aggr, @Nullable AvlNode<E> node) {
213    if (node == null) {
214      return 0;
215    }
216    // The cast is safe because we call this method only if hasUpperBound().
217    int cmp =
218        comparator()
219            .compare(uncheckedCastNullableTToT(range.getUpperEndpoint()), node.getElement());
220    if (cmp > 0) {
221      return aggregateAboveRange(aggr, node.right);
222    } else if (cmp == 0) {
223      switch (range.getUpperBoundType()) {
224        case OPEN:
225          return aggr.nodeAggregate(node) + aggr.treeAggregate(node.right);
226        case CLOSED:
227          return aggr.treeAggregate(node.right);
228      }
229      throw new AssertionError();
230    } else {
231      return aggr.treeAggregate(node.right)
232          + aggr.nodeAggregate(node)
233          + aggregateAboveRange(aggr, node.left);
234    }
235  }
236
237  @Override
238  public int size() {
239    return Ints.saturatedCast(aggregateForEntries(Aggregate.SIZE));
240  }
241
242  @Override
243  int internalDistinctElements() {
244    return Ints.saturatedCast(aggregateForEntries(Aggregate.DISTINCT));
245  }
246
247  private static int distinctElements(@Nullable AvlNode<?> node) {
248    return (node == null) ? 0 : node.distinctElements;
249  }
250
251  @Override
252  public int count(@Nullable Object element) {
253    try {
254      @SuppressWarnings("unchecked")
255      E e = (E) element;
256      AvlNode<E> root = rootReference.get();
257      if (!range.contains(e) || root == null) {
258        return 0;
259      }
260      return root.count(comparator(), e);
261    } catch (ClassCastException | NullPointerException e) {
262      return 0;
263    }
264  }
265
266  @CanIgnoreReturnValue
267  @Override
268  public int add(@ParametricNullness E element, int occurrences) {
269    checkNonnegative(occurrences, "occurrences");
270    if (occurrences == 0) {
271      return count(element);
272    }
273    checkArgument(range.contains(element));
274    AvlNode<E> root = rootReference.get();
275    if (root == null) {
276      int unused = comparator().compare(element, element);
277      AvlNode<E> newRoot = new AvlNode<>(element, occurrences);
278      successor(header, newRoot, header);
279      rootReference.checkAndSet(root, newRoot);
280      return 0;
281    }
282    int[] result = new int[1]; // used as a mutable int reference to hold result
283    AvlNode<E> newRoot = root.add(comparator(), element, occurrences, result);
284    rootReference.checkAndSet(root, newRoot);
285    return result[0];
286  }
287
288  @CanIgnoreReturnValue
289  @Override
290  public int remove(@Nullable Object element, int occurrences) {
291    checkNonnegative(occurrences, "occurrences");
292    if (occurrences == 0) {
293      return count(element);
294    }
295    AvlNode<E> root = rootReference.get();
296    int[] result = new int[1]; // used as a mutable int reference to hold result
297    AvlNode<E> newRoot;
298    try {
299      @SuppressWarnings("unchecked")
300      E e = (E) element;
301      if (!range.contains(e) || root == null) {
302        return 0;
303      }
304      newRoot = root.remove(comparator(), e, occurrences, result);
305    } catch (ClassCastException | NullPointerException e) {
306      return 0;
307    }
308    rootReference.checkAndSet(root, newRoot);
309    return result[0];
310  }
311
312  @CanIgnoreReturnValue
313  @Override
314  public int setCount(@ParametricNullness E element, int count) {
315    checkNonnegative(count, "count");
316    if (!range.contains(element)) {
317      checkArgument(count == 0);
318      return 0;
319    }
320
321    AvlNode<E> root = rootReference.get();
322    if (root == null) {
323      if (count > 0) {
324        add(element, count);
325      }
326      return 0;
327    }
328    int[] result = new int[1]; // used as a mutable int reference to hold result
329    AvlNode<E> newRoot = root.setCount(comparator(), element, count, result);
330    rootReference.checkAndSet(root, newRoot);
331    return result[0];
332  }
333
334  @CanIgnoreReturnValue
335  @Override
336  public boolean setCount(@ParametricNullness E element, int oldCount, int newCount) {
337    checkNonnegative(newCount, "newCount");
338    checkNonnegative(oldCount, "oldCount");
339    checkArgument(range.contains(element));
340
341    AvlNode<E> root = rootReference.get();
342    if (root == null) {
343      if (oldCount == 0) {
344        if (newCount > 0) {
345          add(element, newCount);
346        }
347        return true;
348      } else {
349        // Validate the element even when its count cannot match.
350        int unused = comparator().compare(element, element);
351        return false;
352      }
353    }
354    int[] result = new int[1]; // used as a mutable int reference to hold result
355    AvlNode<E> newRoot = root.setCount(comparator(), element, oldCount, newCount, result);
356    rootReference.checkAndSet(root, newRoot);
357    return result[0] == oldCount;
358  }
359
360  @Override
361  public void clear() {
362    if (!range.hasLowerBound() && !range.hasUpperBound()) {
363      // We can do this in O(n) rather than removing one by one, which could force rebalancing.
364      for (AvlNode<E> current = header.succ(); current != header; ) {
365        AvlNode<E> next = current.succ();
366
367        current.elemCount = 0;
368        // Also clear these fields so that one deleted Entry doesn't retain all elements.
369        current.left = null;
370        current.right = null;
371        current.pred = null;
372        current.succ = null;
373
374        current = next;
375      }
376      successor(header, header);
377      rootReference.clear();
378    } else {
379      // TODO(cpovirk): Perhaps we can optimize in this case, too?
380      Iterators.clear(internalEntryIterator());
381    }
382  }
383
384  private Entry<E> wrapEntry(AvlNode<E> baseEntry) {
385    return new Multisets.AbstractEntry<E>() {
386      @Override
387      @ParametricNullness
388      public E getElement() {
389        return baseEntry.getElement();
390      }
391
392      @Override
393      public int getCount() {
394        int result = baseEntry.getCount();
395        if (result == 0) {
396          return count(getElement());
397        } else {
398          return result;
399        }
400      }
401    };
402  }
403
404  /** Returns the first node in the tree that is in range. */
405  private @Nullable AvlNode<E> firstNode() {
406    AvlNode<E> root = rootReference.get();
407    if (root == null) {
408      return null;
409    }
410    AvlNode<E> node;
411    if (range.hasLowerBound()) {
412      // The cast is safe because of the hasLowerBound check.
413      E endpoint = uncheckedCastNullableTToT(range.getLowerEndpoint());
414      node = root.ceiling(comparator(), endpoint);
415      if (node == null) {
416        return null;
417      }
418      if (range.getLowerBoundType() == BoundType.OPEN
419          && comparator().compare(endpoint, node.getElement()) == 0) {
420        node = node.succ();
421      }
422    } else {
423      node = header.succ();
424    }
425    return (node == header || !range.contains(node.getElement())) ? null : node;
426  }
427
428  private @Nullable AvlNode<E> lastNode() {
429    AvlNode<E> root = rootReference.get();
430    if (root == null) {
431      return null;
432    }
433    AvlNode<E> node;
434    if (range.hasUpperBound()) {
435      // The cast is safe because of the hasUpperBound check.
436      E endpoint = uncheckedCastNullableTToT(range.getUpperEndpoint());
437      node = root.floor(comparator(), endpoint);
438      if (node == null) {
439        return null;
440      }
441      if (range.getUpperBoundType() == BoundType.OPEN
442          && comparator().compare(endpoint, node.getElement()) == 0) {
443        node = node.pred();
444      }
445    } else {
446      node = header.pred();
447    }
448    return (node == header || !range.contains(node.getElement())) ? null : node;
449  }
450
451  @Override
452  Iterator<E> elementIterator() {
453    return Multisets.elementIterator(internalEntryIterator());
454  }
455
456  @Override
457  Iterator<Entry<E>> internalEntryIterator() {
458    return new Iterator<Entry<E>>() {
459      @Nullable AvlNode<E> current = firstNode();
460      @Nullable Entry<E> prevEntry;
461
462      @Override
463      public boolean hasNext() {
464        if (current == null) {
465          return false;
466        } else if (range.tooHigh(current.getElement())) {
467          current = null;
468          return false;
469        } else {
470          return true;
471        }
472      }
473
474      @Override
475      public Entry<E> next() {
476        if (!hasNext()) {
477          throw new NoSuchElementException();
478        }
479        // requireNonNull is safe because current is only nulled out after iteration is complete.
480        Entry<E> result = wrapEntry(requireNonNull(current));
481        prevEntry = result;
482        if (current.succ() == header) {
483          current = null;
484        } else {
485          current = current.succ();
486        }
487        return result;
488      }
489
490      @Override
491      public void remove() {
492        checkState(prevEntry != null, "no calls to next() since the last call to remove()");
493        setCount(prevEntry.getElement(), 0);
494        prevEntry = null;
495      }
496    };
497  }
498
499  @Override
500  Iterator<Entry<E>> descendingEntryIterator() {
501    return new Iterator<Entry<E>>() {
502      @Nullable AvlNode<E> current = lastNode();
503      @Nullable Entry<E> prevEntry = null;
504
505      @Override
506      public boolean hasNext() {
507        if (current == null) {
508          return false;
509        } else if (range.tooLow(current.getElement())) {
510          current = null;
511          return false;
512        } else {
513          return true;
514        }
515      }
516
517      @Override
518      public Entry<E> next() {
519        if (!hasNext()) {
520          throw new NoSuchElementException();
521        }
522        // requireNonNull is safe because current is only nulled out after iteration is complete.
523        requireNonNull(current);
524        Entry<E> result = wrapEntry(current);
525        prevEntry = result;
526        if (current.pred() == header) {
527          current = null;
528        } else {
529          current = current.pred();
530        }
531        return result;
532      }
533
534      @Override
535      public void remove() {
536        checkState(prevEntry != null, "no calls to next() since the last call to remove()");
537        setCount(prevEntry.getElement(), 0);
538        prevEntry = null;
539      }
540    };
541  }
542
543  @Override
544  public void forEachEntry(ObjIntConsumer<? super E> action) {
545    checkNotNull(action);
546    for (AvlNode<E> node = firstNode();
547        node != header && node != null && !range.tooHigh(node.getElement());
548        node = node.succ()) {
549      action.accept(node.getElement(), node.getCount());
550    }
551  }
552
553  @Override
554  public Iterator<E> iterator() {
555    return Multisets.iteratorImpl(this);
556  }
557
558  @Override
559  public SortedMultiset<E> headMultiset(@ParametricNullness E upperBound, BoundType boundType) {
560    return new TreeMultiset<>(
561        rootReference,
562        range.intersect(GeneralRange.upTo(comparator(), upperBound, boundType)),
563        header);
564  }
565
566  @Override
567  public SortedMultiset<E> tailMultiset(@ParametricNullness E lowerBound, BoundType boundType) {
568    return new TreeMultiset<>(
569        rootReference,
570        range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)),
571        header);
572  }
573
574  private static final class Reference<T> {
575    private @Nullable T value;
576
577    @Nullable T get() {
578      return value;
579    }
580
581    void checkAndSet(@Nullable T expected, @Nullable T newValue) {
582      if (value != expected) {
583        throw new ConcurrentModificationException();
584      }
585      value = newValue;
586    }
587
588    void clear() {
589      value = null;
590    }
591  }
592
593  private static final class AvlNode<E extends @Nullable Object> {
594    /*
595     * For "normal" nodes, the type of this field is `E`, not `@Nullable E` (though note that E is a
596     * type that can include null, as in a TreeMultiset<@Nullable String>).
597     *
598     * For the header node, though, this field contains `null`, regardless of the type of the
599     * multiset.
600     *
601     * Most code that operates on an AvlNode never operates on the header node. Such code can access
602     * the elem field without a null check by calling getElement().
603     */
604    private final @Nullable E elem;
605
606    // elemCount is 0 if and only if this node has been deleted.
607    private int elemCount;
608
609    private int distinctElements;
610    private long totalCount;
611    private int height;
612    private @Nullable AvlNode<E> left;
613    private @Nullable AvlNode<E> right;
614    /*
615     * pred and succ are nullable after construction, but we always call successor() to initialize
616     * them immediately thereafter.
617     *
618     * They may be subsequently nulled out by TreeMultiset.clear(). I think that the only place that
619     * we can reference a node whose fields have been cleared is inside the iterator (and presumably
620     * only under concurrent modification).
621     *
622     * To access these fields when you know that they are not null, call the pred() and succ()
623     * methods, which perform null checks before returning the fields.
624     */
625    private @Nullable AvlNode<E> pred;
626    private @Nullable AvlNode<E> succ;
627
628    AvlNode(@ParametricNullness E elem, int elemCount) {
629      checkArgument(elemCount > 0);
630      this.elem = elem;
631      this.elemCount = elemCount;
632      this.totalCount = elemCount;
633      this.distinctElements = 1;
634      this.height = 1;
635      this.left = null;
636      this.right = null;
637    }
638
639    /** Constructor for the header node. */
640    AvlNode() {
641      this.elem = null;
642      this.elemCount = 1;
643    }
644
645    // For discussion of pred() and succ(), see the comment on the pred and succ fields.
646
647    private AvlNode<E> pred() {
648      return requireNonNull(pred);
649    }
650
651    private AvlNode<E> succ() {
652      return requireNonNull(succ);
653    }
654
655    int count(Comparator<? super E> comparator, @ParametricNullness E e) {
656      int cmp = comparator.compare(e, getElement());
657      if (cmp < 0) {
658        return (left == null) ? 0 : left.count(comparator, e);
659      } else if (cmp > 0) {
660        return (right == null) ? 0 : right.count(comparator, e);
661      } else {
662        return elemCount;
663      }
664    }
665
666    @CanIgnoreReturnValue
667    private AvlNode<E> addRightChild(@ParametricNullness E e, int count) {
668      right = new AvlNode<>(e, count);
669      successor(this, right, succ());
670      height = max(2, height);
671      distinctElements++;
672      totalCount += count;
673      return this;
674    }
675
676    @CanIgnoreReturnValue
677    private AvlNode<E> addLeftChild(@ParametricNullness E e, int count) {
678      left = new AvlNode<>(e, count);
679      successor(pred(), left, this);
680      height = max(2, height);
681      distinctElements++;
682      totalCount += count;
683      return this;
684    }
685
686    AvlNode<E> add(
687        Comparator<? super E> comparator, @ParametricNullness E e, int count, int[] result) {
688      /*
689       * It speeds things up considerably to unconditionally add count to totalCount here,
690       * but that destroys failure atomicity in the case of count overflow. =(
691       */
692      int cmp = comparator.compare(e, getElement());
693      if (cmp < 0) {
694        AvlNode<E> initLeft = left;
695        if (initLeft == null) {
696          result[0] = 0;
697          return addLeftChild(e, count);
698        }
699        int initHeight = initLeft.height;
700
701        left = initLeft.add(comparator, e, count, result);
702        if (result[0] == 0) {
703          distinctElements++;
704        }
705        this.totalCount += count;
706        return (left.height == initHeight) ? this : rebalance();
707      } else if (cmp > 0) {
708        AvlNode<E> initRight = right;
709        if (initRight == null) {
710          result[0] = 0;
711          return addRightChild(e, count);
712        }
713        int initHeight = initRight.height;
714
715        right = initRight.add(comparator, e, count, result);
716        if (result[0] == 0) {
717          distinctElements++;
718        }
719        this.totalCount += count;
720        return (right.height == initHeight) ? this : rebalance();
721      }
722
723      // adding count to me!  No rebalance possible.
724      result[0] = elemCount;
725      long resultCount = (long) elemCount + count;
726      checkArgument(resultCount <= Integer.MAX_VALUE);
727      this.elemCount += count;
728      this.totalCount += count;
729      return this;
730    }
731
732    @Nullable AvlNode<E> remove(
733        Comparator<? super E> comparator, @ParametricNullness E e, int count, int[] result) {
734      int cmp = comparator.compare(e, getElement());
735      if (cmp < 0) {
736        AvlNode<E> initLeft = left;
737        if (initLeft == null) {
738          result[0] = 0;
739          return this;
740        }
741
742        left = initLeft.remove(comparator, e, count, result);
743
744        if (result[0] > 0) {
745          if (count >= result[0]) {
746            this.distinctElements--;
747            this.totalCount -= result[0];
748          } else {
749            this.totalCount -= count;
750          }
751        }
752        return (result[0] == 0) ? this : rebalance();
753      } else if (cmp > 0) {
754        AvlNode<E> initRight = right;
755        if (initRight == null) {
756          result[0] = 0;
757          return this;
758        }
759
760        right = initRight.remove(comparator, e, count, result);
761
762        if (result[0] > 0) {
763          if (count >= result[0]) {
764            this.distinctElements--;
765            this.totalCount -= result[0];
766          } else {
767            this.totalCount -= count;
768          }
769        }
770        return rebalance();
771      }
772
773      // removing count from me!
774      result[0] = elemCount;
775      if (count >= elemCount) {
776        return deleteMe();
777      } else {
778        this.elemCount -= count;
779        this.totalCount -= count;
780        return this;
781      }
782    }
783
784    @Nullable AvlNode<E> setCount(
785        Comparator<? super E> comparator, @ParametricNullness E e, int count, int[] result) {
786      int cmp = comparator.compare(e, getElement());
787      if (cmp < 0) {
788        AvlNode<E> initLeft = left;
789        if (initLeft == null) {
790          result[0] = 0;
791          return (count > 0) ? addLeftChild(e, count) : this;
792        }
793
794        left = initLeft.setCount(comparator, e, count, result);
795
796        if (count == 0 && result[0] != 0) {
797          this.distinctElements--;
798        } else if (count > 0 && result[0] == 0) {
799          this.distinctElements++;
800        }
801
802        this.totalCount += count - result[0];
803        return rebalance();
804      } else if (cmp > 0) {
805        AvlNode<E> initRight = right;
806        if (initRight == null) {
807          result[0] = 0;
808          return (count > 0) ? addRightChild(e, count) : this;
809        }
810
811        right = initRight.setCount(comparator, e, count, result);
812
813        if (count == 0 && result[0] != 0) {
814          this.distinctElements--;
815        } else if (count > 0 && result[0] == 0) {
816          this.distinctElements++;
817        }
818
819        this.totalCount += count - result[0];
820        return rebalance();
821      }
822
823      // setting my count
824      result[0] = elemCount;
825      if (count == 0) {
826        return deleteMe();
827      }
828      this.totalCount += count - elemCount;
829      this.elemCount = count;
830      return this;
831    }
832
833    @Nullable AvlNode<E> setCount(
834        Comparator<? super E> comparator,
835        @ParametricNullness E e,
836        int expectedCount,
837        int newCount,
838        int[] result) {
839      int cmp = comparator.compare(e, getElement());
840      if (cmp < 0) {
841        AvlNode<E> initLeft = left;
842        if (initLeft == null) {
843          result[0] = 0;
844          if (expectedCount == 0 && newCount > 0) {
845            return addLeftChild(e, newCount);
846          }
847          return this;
848        }
849
850        left = initLeft.setCount(comparator, e, expectedCount, newCount, result);
851
852        if (result[0] == expectedCount) {
853          if (newCount == 0 && result[0] != 0) {
854            this.distinctElements--;
855          } else if (newCount > 0 && result[0] == 0) {
856            this.distinctElements++;
857          }
858          this.totalCount += newCount - result[0];
859        }
860        return rebalance();
861      } else if (cmp > 0) {
862        AvlNode<E> initRight = right;
863        if (initRight == null) {
864          result[0] = 0;
865          if (expectedCount == 0 && newCount > 0) {
866            return addRightChild(e, newCount);
867          }
868          return this;
869        }
870
871        right = initRight.setCount(comparator, e, expectedCount, newCount, result);
872
873        if (result[0] == expectedCount) {
874          if (newCount == 0 && result[0] != 0) {
875            this.distinctElements--;
876          } else if (newCount > 0 && result[0] == 0) {
877            this.distinctElements++;
878          }
879          this.totalCount += newCount - result[0];
880        }
881        return rebalance();
882      }
883
884      // setting my count
885      result[0] = elemCount;
886      if (expectedCount == elemCount) {
887        if (newCount == 0) {
888          return deleteMe();
889        }
890        this.totalCount += newCount - elemCount;
891        this.elemCount = newCount;
892      }
893      return this;
894    }
895
896    private @Nullable AvlNode<E> deleteMe() {
897      int oldElemCount = this.elemCount;
898      this.elemCount = 0;
899      successor(pred(), succ());
900      if (left == null) {
901        return right;
902      } else if (right == null) {
903        return left;
904      } else if (left.height >= right.height) {
905        AvlNode<E> newTop = pred();
906        // newTop is the maximum node in my left subtree
907        newTop.left = left.removeMax(newTop);
908        newTop.right = right;
909        newTop.distinctElements = distinctElements - 1;
910        newTop.totalCount = totalCount - oldElemCount;
911        return newTop.rebalance();
912      } else {
913        AvlNode<E> newTop = succ();
914        newTop.right = right.removeMin(newTop);
915        newTop.left = left;
916        newTop.distinctElements = distinctElements - 1;
917        newTop.totalCount = totalCount - oldElemCount;
918        return newTop.rebalance();
919      }
920    }
921
922    // Removes the minimum node from this subtree to be reused elsewhere
923    private @Nullable AvlNode<E> removeMin(AvlNode<E> node) {
924      if (left == null) {
925        return right;
926      } else {
927        left = left.removeMin(node);
928        distinctElements--;
929        totalCount -= node.elemCount;
930        return rebalance();
931      }
932    }
933
934    // Removes the maximum node from this subtree to be reused elsewhere
935    private @Nullable AvlNode<E> removeMax(AvlNode<E> node) {
936      if (right == null) {
937        return left;
938      } else {
939        right = right.removeMax(node);
940        distinctElements--;
941        totalCount -= node.elemCount;
942        return rebalance();
943      }
944    }
945
946    private void recomputeMultiset() {
947      this.distinctElements = 1 + distinctElements(left) + distinctElements(right);
948      this.totalCount = elemCount + totalCount(left) + totalCount(right);
949    }
950
951    private void recomputeHeight() {
952      this.height = 1 + max(height(left), height(right));
953    }
954
955    private void recompute() {
956      recomputeMultiset();
957      recomputeHeight();
958    }
959
960    private AvlNode<E> rebalance() {
961      switch (balanceFactor()) {
962        case -2:
963          // requireNonNull is safe because right must exist in order to get a negative factor.
964          requireNonNull(right);
965          if (right.balanceFactor() > 0) {
966            right = right.rotateRight();
967          }
968          return rotateLeft();
969        case 2:
970          // requireNonNull is safe because left must exist in order to get a positive factor.
971          requireNonNull(left);
972          if (left.balanceFactor() < 0) {
973            left = left.rotateLeft();
974          }
975          return rotateRight();
976        default:
977          recomputeHeight();
978          return this;
979      }
980    }
981
982    private int balanceFactor() {
983      return height(left) - height(right);
984    }
985
986    private AvlNode<E> rotateLeft() {
987      checkState(right != null);
988      AvlNode<E> newTop = right;
989      this.right = newTop.left;
990      newTop.left = this;
991      newTop.totalCount = this.totalCount;
992      newTop.distinctElements = this.distinctElements;
993      this.recompute();
994      newTop.recomputeHeight();
995      return newTop;
996    }
997
998    private AvlNode<E> rotateRight() {
999      checkState(left != null);
1000      AvlNode<E> newTop = left;
1001      this.left = newTop.right;
1002      newTop.right = this;
1003      newTop.totalCount = this.totalCount;
1004      newTop.distinctElements = this.distinctElements;
1005      this.recompute();
1006      newTop.recomputeHeight();
1007      return newTop;
1008    }
1009
1010    private static long totalCount(@Nullable AvlNode<?> node) {
1011      return (node == null) ? 0 : node.totalCount;
1012    }
1013
1014    private static int height(@Nullable AvlNode<?> node) {
1015      return (node == null) ? 0 : node.height;
1016    }
1017
1018    private @Nullable AvlNode<E> ceiling(
1019        Comparator<? super E> comparator, @ParametricNullness E e) {
1020      int cmp = comparator.compare(e, getElement());
1021      if (cmp < 0) {
1022        return (left == null) ? this : MoreObjects.firstNonNull(left.ceiling(comparator, e), this);
1023      } else if (cmp == 0) {
1024        return this;
1025      } else {
1026        return (right == null) ? null : right.ceiling(comparator, e);
1027      }
1028    }
1029
1030    private @Nullable AvlNode<E> floor(Comparator<? super E> comparator, @ParametricNullness E e) {
1031      int cmp = comparator.compare(e, getElement());
1032      if (cmp > 0) {
1033        return (right == null) ? this : MoreObjects.firstNonNull(right.floor(comparator, e), this);
1034      } else if (cmp == 0) {
1035        return this;
1036      } else {
1037        return (left == null) ? null : left.floor(comparator, e);
1038      }
1039    }
1040
1041    @ParametricNullness
1042    E getElement() {
1043      // For discussion of this cast, see the comment on the elem field.
1044      return uncheckedCastNullableTToT(elem);
1045    }
1046
1047    int getCount() {
1048      return elemCount;
1049    }
1050
1051    @Override
1052    public String toString() {
1053      return Multisets.immutableEntry(getElement(), getCount()).toString();
1054    }
1055  }
1056
1057  private static <T extends @Nullable Object> void successor(AvlNode<T> a, AvlNode<T> b) {
1058    a.succ = b;
1059    b.pred = a;
1060  }
1061
1062  private static <T extends @Nullable Object> void successor(
1063      AvlNode<T> a, AvlNode<T> b, AvlNode<T> c) {
1064    successor(a, b);
1065    successor(b, c);
1066  }
1067
1068  /*
1069   * TODO(jlevy): Decide whether entrySet() should return entries with an equals() method that
1070   * calls the comparator to compare the two keys. If that change is made,
1071   * AbstractMultiset.equals() can simply check whether two multisets have equal entry sets.
1072   */
1073
1074  /**
1075   * @serialData the comparator, the number of distinct elements, the first element, its count, the
1076   *     second element, its count, and so on
1077   */
1078  @GwtIncompatible
1079  @J2ktIncompatible
1080    private void writeObject(ObjectOutputStream stream) throws IOException {
1081    stream.defaultWriteObject();
1082    stream.writeObject(elementSet().comparator());
1083    Serialization.writeMultiset(this, stream);
1084  }
1085
1086  @J2ktIncompatible
1087  @GwtIncompatible
1088    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
1089    stream.defaultReadObject();
1090    @SuppressWarnings("unchecked")
1091    // reading data stored by writeObject
1092    Comparator<? super E> comparator = (Comparator<? super E>) requireNonNull(stream.readObject());
1093    deserializationReplacement = new TreeMultiset<>(comparator);
1094    Serialization.populateMultiset(deserializationReplacement, stream);
1095  }
1096
1097  @J2ktIncompatible
1098  @GwtIncompatible
1099    private Object readResolve() {
1100    return requireNonNull(deserializationReplacement); // set by readObject
1101  }
1102
1103  @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 1;
1104}