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 distinctElements() { 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 return false; 350 } 351 } 352 int[] result = new int[1]; // used as a mutable int reference to hold result 353 AvlNode<E> newRoot = root.setCount(comparator(), element, oldCount, newCount, result); 354 rootReference.checkAndSet(root, newRoot); 355 return result[0] == oldCount; 356 } 357 358 @Override 359 public void clear() { 360 if (!range.hasLowerBound() && !range.hasUpperBound()) { 361 // We can do this in O(n) rather than removing one by one, which could force rebalancing. 362 for (AvlNode<E> current = header.succ(); current != header; ) { 363 AvlNode<E> next = current.succ(); 364 365 current.elemCount = 0; 366 // Also clear these fields so that one deleted Entry doesn't retain all elements. 367 current.left = null; 368 current.right = null; 369 current.pred = null; 370 current.succ = null; 371 372 current = next; 373 } 374 successor(header, header); 375 rootReference.clear(); 376 } else { 377 // TODO(cpovirk): Perhaps we can optimize in this case, too? 378 Iterators.clear(entryIterator()); 379 } 380 } 381 382 private Entry<E> wrapEntry(AvlNode<E> baseEntry) { 383 return new Multisets.AbstractEntry<E>() { 384 @Override 385 @ParametricNullness 386 public E getElement() { 387 return baseEntry.getElement(); 388 } 389 390 @Override 391 public int getCount() { 392 int result = baseEntry.getCount(); 393 if (result == 0) { 394 return count(getElement()); 395 } else { 396 return result; 397 } 398 } 399 }; 400 } 401 402 /** Returns the first node in the tree that is in range. */ 403 private @Nullable AvlNode<E> firstNode() { 404 AvlNode<E> root = rootReference.get(); 405 if (root == null) { 406 return null; 407 } 408 AvlNode<E> node; 409 if (range.hasLowerBound()) { 410 // The cast is safe because of the hasLowerBound check. 411 E endpoint = uncheckedCastNullableTToT(range.getLowerEndpoint()); 412 node = root.ceiling(comparator(), endpoint); 413 if (node == null) { 414 return null; 415 } 416 if (range.getLowerBoundType() == BoundType.OPEN 417 && comparator().compare(endpoint, node.getElement()) == 0) { 418 node = node.succ(); 419 } 420 } else { 421 node = header.succ(); 422 } 423 return (node == header || !range.contains(node.getElement())) ? null : node; 424 } 425 426 private @Nullable AvlNode<E> lastNode() { 427 AvlNode<E> root = rootReference.get(); 428 if (root == null) { 429 return null; 430 } 431 AvlNode<E> node; 432 if (range.hasUpperBound()) { 433 // The cast is safe because of the hasUpperBound check. 434 E endpoint = uncheckedCastNullableTToT(range.getUpperEndpoint()); 435 node = root.floor(comparator(), endpoint); 436 if (node == null) { 437 return null; 438 } 439 if (range.getUpperBoundType() == BoundType.OPEN 440 && comparator().compare(endpoint, node.getElement()) == 0) { 441 node = node.pred(); 442 } 443 } else { 444 node = header.pred(); 445 } 446 return (node == header || !range.contains(node.getElement())) ? null : node; 447 } 448 449 @Override 450 Iterator<E> elementIterator() { 451 return Multisets.elementIterator(entryIterator()); 452 } 453 454 @Override 455 Iterator<Entry<E>> entryIterator() { 456 return new Iterator<Entry<E>>() { 457 private @Nullable AvlNode<E> current = firstNode(); 458 private @Nullable Entry<E> prevEntry; 459 460 @Override 461 public boolean hasNext() { 462 if (current == null) { 463 return false; 464 } else if (range.tooHigh(current.getElement())) { 465 current = null; 466 return false; 467 } else { 468 return true; 469 } 470 } 471 472 @Override 473 public Entry<E> next() { 474 if (!hasNext()) { 475 throw new NoSuchElementException(); 476 } 477 // requireNonNull is safe because current is only nulled out after iteration is complete. 478 Entry<E> result = wrapEntry(requireNonNull(current)); 479 prevEntry = result; 480 if (current.succ() == header) { 481 current = null; 482 } else { 483 current = current.succ(); 484 } 485 return result; 486 } 487 488 @Override 489 public void remove() { 490 checkState(prevEntry != null, "no calls to next() since the last call to remove()"); 491 setCount(prevEntry.getElement(), 0); 492 prevEntry = null; 493 } 494 }; 495 } 496 497 @Override 498 Iterator<Entry<E>> descendingEntryIterator() { 499 return new Iterator<Entry<E>>() { 500 private @Nullable AvlNode<E> current = lastNode(); 501 private @Nullable Entry<E> prevEntry = null; 502 503 @Override 504 public boolean hasNext() { 505 if (current == null) { 506 return false; 507 } else if (range.tooLow(current.getElement())) { 508 current = null; 509 return false; 510 } else { 511 return true; 512 } 513 } 514 515 @Override 516 public Entry<E> next() { 517 if (!hasNext()) { 518 throw new NoSuchElementException(); 519 } 520 // requireNonNull is safe because current is only nulled out after iteration is complete. 521 requireNonNull(current); 522 Entry<E> result = wrapEntry(current); 523 prevEntry = result; 524 if (current.pred() == header) { 525 current = null; 526 } else { 527 current = current.pred(); 528 } 529 return result; 530 } 531 532 @Override 533 public void remove() { 534 checkState(prevEntry != null, "no calls to next() since the last call to remove()"); 535 setCount(prevEntry.getElement(), 0); 536 prevEntry = null; 537 } 538 }; 539 } 540 541 @Override 542 public void forEachEntry(ObjIntConsumer<? super E> action) { 543 checkNotNull(action); 544 for (AvlNode<E> node = firstNode(); 545 node != header && node != null && !range.tooHigh(node.getElement()); 546 node = node.succ()) { 547 action.accept(node.getElement(), node.getCount()); 548 } 549 } 550 551 @Override 552 public Iterator<E> iterator() { 553 return Multisets.iteratorImpl(this); 554 } 555 556 @Override 557 public SortedMultiset<E> headMultiset(@ParametricNullness E upperBound, BoundType boundType) { 558 return new TreeMultiset<>( 559 rootReference, 560 range.intersect(GeneralRange.upTo(comparator(), upperBound, boundType)), 561 header); 562 } 563 564 @Override 565 public SortedMultiset<E> tailMultiset(@ParametricNullness E lowerBound, BoundType boundType) { 566 return new TreeMultiset<>( 567 rootReference, 568 range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)), 569 header); 570 } 571 572 private static final class Reference<T> { 573 private @Nullable T value; 574 575 @Nullable T get() { 576 return value; 577 } 578 579 void checkAndSet(@Nullable T expected, @Nullable T newValue) { 580 if (value != expected) { 581 throw new ConcurrentModificationException(); 582 } 583 value = newValue; 584 } 585 586 void clear() { 587 value = null; 588 } 589 } 590 591 private static final class AvlNode<E extends @Nullable Object> { 592 /* 593 * For "normal" nodes, the type of this field is `E`, not `@Nullable E` (though note that E is a 594 * type that can include null, as in a TreeMultiset<@Nullable String>). 595 * 596 * For the header node, though, this field contains `null`, regardless of the type of the 597 * multiset. 598 * 599 * Most code that operates on an AvlNode never operates on the header node. Such code can access 600 * the elem field without a null check by calling getElement(). 601 */ 602 private final @Nullable E elem; 603 604 // elemCount is 0 iff this node has been deleted. 605 private int elemCount; 606 607 private int distinctElements; 608 private long totalCount; 609 private int height; 610 private @Nullable AvlNode<E> left; 611 private @Nullable AvlNode<E> right; 612 /* 613 * pred and succ are nullable after construction, but we always call successor() to initialize 614 * them immediately thereafter. 615 * 616 * They may be subsequently nulled out by TreeMultiset.clear(). I think that the only place that 617 * we can reference a node whose fields have been cleared is inside the iterator (and presumably 618 * only under concurrent modification). 619 * 620 * To access these fields when you know that they are not null, call the pred() and succ() 621 * methods, which perform null checks before returning the fields. 622 */ 623 private @Nullable AvlNode<E> pred; 624 private @Nullable AvlNode<E> succ; 625 626 AvlNode(@ParametricNullness E elem, int elemCount) { 627 checkArgument(elemCount > 0); 628 this.elem = elem; 629 this.elemCount = elemCount; 630 this.totalCount = elemCount; 631 this.distinctElements = 1; 632 this.height = 1; 633 this.left = null; 634 this.right = null; 635 } 636 637 /** Constructor for the header node. */ 638 AvlNode() { 639 this.elem = null; 640 this.elemCount = 1; 641 } 642 643 // For discussion of pred() and succ(), see the comment on the pred and succ fields. 644 645 private AvlNode<E> pred() { 646 return requireNonNull(pred); 647 } 648 649 private AvlNode<E> succ() { 650 return requireNonNull(succ); 651 } 652 653 int count(Comparator<? super E> comparator, @ParametricNullness E e) { 654 int cmp = comparator.compare(e, getElement()); 655 if (cmp < 0) { 656 return (left == null) ? 0 : left.count(comparator, e); 657 } else if (cmp > 0) { 658 return (right == null) ? 0 : right.count(comparator, e); 659 } else { 660 return elemCount; 661 } 662 } 663 664 @CanIgnoreReturnValue 665 private AvlNode<E> addRightChild(@ParametricNullness E e, int count) { 666 right = new AvlNode<>(e, count); 667 successor(this, right, succ()); 668 height = max(2, height); 669 distinctElements++; 670 totalCount += count; 671 return this; 672 } 673 674 @CanIgnoreReturnValue 675 private AvlNode<E> addLeftChild(@ParametricNullness E e, int count) { 676 left = new AvlNode<>(e, count); 677 successor(pred(), left, this); 678 height = max(2, height); 679 distinctElements++; 680 totalCount += count; 681 return this; 682 } 683 684 AvlNode<E> add( 685 Comparator<? super E> comparator, @ParametricNullness E e, int count, int[] result) { 686 /* 687 * It speeds things up considerably to unconditionally add count to totalCount here, 688 * but that destroys failure atomicity in the case of count overflow. =( 689 */ 690 int cmp = comparator.compare(e, getElement()); 691 if (cmp < 0) { 692 AvlNode<E> initLeft = left; 693 if (initLeft == null) { 694 result[0] = 0; 695 return addLeftChild(e, count); 696 } 697 int initHeight = initLeft.height; 698 699 left = initLeft.add(comparator, e, count, result); 700 if (result[0] == 0) { 701 distinctElements++; 702 } 703 this.totalCount += count; 704 return (left.height == initHeight) ? this : rebalance(); 705 } else if (cmp > 0) { 706 AvlNode<E> initRight = right; 707 if (initRight == null) { 708 result[0] = 0; 709 return addRightChild(e, count); 710 } 711 int initHeight = initRight.height; 712 713 right = initRight.add(comparator, e, count, result); 714 if (result[0] == 0) { 715 distinctElements++; 716 } 717 this.totalCount += count; 718 return (right.height == initHeight) ? this : rebalance(); 719 } 720 721 // adding count to me! No rebalance possible. 722 result[0] = elemCount; 723 long resultCount = (long) elemCount + count; 724 checkArgument(resultCount <= Integer.MAX_VALUE); 725 this.elemCount += count; 726 this.totalCount += count; 727 return this; 728 } 729 730 @Nullable AvlNode<E> remove( 731 Comparator<? super E> comparator, @ParametricNullness E e, int count, int[] result) { 732 int cmp = comparator.compare(e, getElement()); 733 if (cmp < 0) { 734 AvlNode<E> initLeft = left; 735 if (initLeft == null) { 736 result[0] = 0; 737 return this; 738 } 739 740 left = initLeft.remove(comparator, e, count, result); 741 742 if (result[0] > 0) { 743 if (count >= result[0]) { 744 this.distinctElements--; 745 this.totalCount -= result[0]; 746 } else { 747 this.totalCount -= count; 748 } 749 } 750 return (result[0] == 0) ? this : rebalance(); 751 } else if (cmp > 0) { 752 AvlNode<E> initRight = right; 753 if (initRight == null) { 754 result[0] = 0; 755 return this; 756 } 757 758 right = initRight.remove(comparator, e, count, result); 759 760 if (result[0] > 0) { 761 if (count >= result[0]) { 762 this.distinctElements--; 763 this.totalCount -= result[0]; 764 } else { 765 this.totalCount -= count; 766 } 767 } 768 return rebalance(); 769 } 770 771 // removing count from me! 772 result[0] = elemCount; 773 if (count >= elemCount) { 774 return deleteMe(); 775 } else { 776 this.elemCount -= count; 777 this.totalCount -= count; 778 return this; 779 } 780 } 781 782 @Nullable AvlNode<E> setCount( 783 Comparator<? super E> comparator, @ParametricNullness E e, int count, int[] result) { 784 int cmp = comparator.compare(e, getElement()); 785 if (cmp < 0) { 786 AvlNode<E> initLeft = left; 787 if (initLeft == null) { 788 result[0] = 0; 789 return (count > 0) ? addLeftChild(e, count) : this; 790 } 791 792 left = initLeft.setCount(comparator, e, count, result); 793 794 if (count == 0 && result[0] != 0) { 795 this.distinctElements--; 796 } else if (count > 0 && result[0] == 0) { 797 this.distinctElements++; 798 } 799 800 this.totalCount += count - result[0]; 801 return rebalance(); 802 } else if (cmp > 0) { 803 AvlNode<E> initRight = right; 804 if (initRight == null) { 805 result[0] = 0; 806 return (count > 0) ? addRightChild(e, count) : this; 807 } 808 809 right = initRight.setCount(comparator, e, count, result); 810 811 if (count == 0 && result[0] != 0) { 812 this.distinctElements--; 813 } else if (count > 0 && result[0] == 0) { 814 this.distinctElements++; 815 } 816 817 this.totalCount += count - result[0]; 818 return rebalance(); 819 } 820 821 // setting my count 822 result[0] = elemCount; 823 if (count == 0) { 824 return deleteMe(); 825 } 826 this.totalCount += count - elemCount; 827 this.elemCount = count; 828 return this; 829 } 830 831 @Nullable AvlNode<E> setCount( 832 Comparator<? super E> comparator, 833 @ParametricNullness E e, 834 int expectedCount, 835 int newCount, 836 int[] result) { 837 int cmp = comparator.compare(e, getElement()); 838 if (cmp < 0) { 839 AvlNode<E> initLeft = left; 840 if (initLeft == null) { 841 result[0] = 0; 842 if (expectedCount == 0 && newCount > 0) { 843 return addLeftChild(e, newCount); 844 } 845 return this; 846 } 847 848 left = initLeft.setCount(comparator, e, expectedCount, newCount, result); 849 850 if (result[0] == expectedCount) { 851 if (newCount == 0 && result[0] != 0) { 852 this.distinctElements--; 853 } else if (newCount > 0 && result[0] == 0) { 854 this.distinctElements++; 855 } 856 this.totalCount += newCount - result[0]; 857 } 858 return rebalance(); 859 } else if (cmp > 0) { 860 AvlNode<E> initRight = right; 861 if (initRight == null) { 862 result[0] = 0; 863 if (expectedCount == 0 && newCount > 0) { 864 return addRightChild(e, newCount); 865 } 866 return this; 867 } 868 869 right = initRight.setCount(comparator, e, expectedCount, newCount, result); 870 871 if (result[0] == expectedCount) { 872 if (newCount == 0 && result[0] != 0) { 873 this.distinctElements--; 874 } else if (newCount > 0 && result[0] == 0) { 875 this.distinctElements++; 876 } 877 this.totalCount += newCount - result[0]; 878 } 879 return rebalance(); 880 } 881 882 // setting my count 883 result[0] = elemCount; 884 if (expectedCount == elemCount) { 885 if (newCount == 0) { 886 return deleteMe(); 887 } 888 this.totalCount += newCount - elemCount; 889 this.elemCount = newCount; 890 } 891 return this; 892 } 893 894 private @Nullable AvlNode<E> deleteMe() { 895 int oldElemCount = this.elemCount; 896 this.elemCount = 0; 897 successor(pred(), succ()); 898 if (left == null) { 899 return right; 900 } else if (right == null) { 901 return left; 902 } else if (left.height >= right.height) { 903 AvlNode<E> newTop = pred(); 904 // newTop is the maximum node in my left subtree 905 newTop.left = left.removeMax(newTop); 906 newTop.right = right; 907 newTop.distinctElements = distinctElements - 1; 908 newTop.totalCount = totalCount - oldElemCount; 909 return newTop.rebalance(); 910 } else { 911 AvlNode<E> newTop = succ(); 912 newTop.right = right.removeMin(newTop); 913 newTop.left = left; 914 newTop.distinctElements = distinctElements - 1; 915 newTop.totalCount = totalCount - oldElemCount; 916 return newTop.rebalance(); 917 } 918 } 919 920 // Removes the minimum node from this subtree to be reused elsewhere 921 private @Nullable AvlNode<E> removeMin(AvlNode<E> node) { 922 if (left == null) { 923 return right; 924 } else { 925 left = left.removeMin(node); 926 distinctElements--; 927 totalCount -= node.elemCount; 928 return rebalance(); 929 } 930 } 931 932 // Removes the maximum node from this subtree to be reused elsewhere 933 private @Nullable AvlNode<E> removeMax(AvlNode<E> node) { 934 if (right == null) { 935 return left; 936 } else { 937 right = right.removeMax(node); 938 distinctElements--; 939 totalCount -= node.elemCount; 940 return rebalance(); 941 } 942 } 943 944 private void recomputeMultiset() { 945 this.distinctElements = 1 + distinctElements(left) + distinctElements(right); 946 this.totalCount = elemCount + totalCount(left) + totalCount(right); 947 } 948 949 private void recomputeHeight() { 950 this.height = 1 + max(height(left), height(right)); 951 } 952 953 private void recompute() { 954 recomputeMultiset(); 955 recomputeHeight(); 956 } 957 958 private AvlNode<E> rebalance() { 959 switch (balanceFactor()) { 960 case -2: 961 // requireNonNull is safe because right must exist in order to get a negative factor. 962 requireNonNull(right); 963 if (right.balanceFactor() > 0) { 964 right = right.rotateRight(); 965 } 966 return rotateLeft(); 967 case 2: 968 // requireNonNull is safe because left must exist in order to get a positive factor. 969 requireNonNull(left); 970 if (left.balanceFactor() < 0) { 971 left = left.rotateLeft(); 972 } 973 return rotateRight(); 974 default: 975 recomputeHeight(); 976 return this; 977 } 978 } 979 980 private int balanceFactor() { 981 return height(left) - height(right); 982 } 983 984 private AvlNode<E> rotateLeft() { 985 checkState(right != null); 986 AvlNode<E> newTop = right; 987 this.right = newTop.left; 988 newTop.left = this; 989 newTop.totalCount = this.totalCount; 990 newTop.distinctElements = this.distinctElements; 991 this.recompute(); 992 newTop.recomputeHeight(); 993 return newTop; 994 } 995 996 private AvlNode<E> rotateRight() { 997 checkState(left != null); 998 AvlNode<E> newTop = left; 999 this.left = newTop.right; 1000 newTop.right = this; 1001 newTop.totalCount = this.totalCount; 1002 newTop.distinctElements = this.distinctElements; 1003 this.recompute(); 1004 newTop.recomputeHeight(); 1005 return newTop; 1006 } 1007 1008 private static long totalCount(@Nullable AvlNode<?> node) { 1009 return (node == null) ? 0 : node.totalCount; 1010 } 1011 1012 private static int height(@Nullable AvlNode<?> node) { 1013 return (node == null) ? 0 : node.height; 1014 } 1015 1016 private @Nullable AvlNode<E> ceiling( 1017 Comparator<? super E> comparator, @ParametricNullness E e) { 1018 int cmp = comparator.compare(e, getElement()); 1019 if (cmp < 0) { 1020 return (left == null) ? this : MoreObjects.firstNonNull(left.ceiling(comparator, e), this); 1021 } else if (cmp == 0) { 1022 return this; 1023 } else { 1024 return (right == null) ? null : right.ceiling(comparator, e); 1025 } 1026 } 1027 1028 private @Nullable AvlNode<E> floor(Comparator<? super E> comparator, @ParametricNullness E e) { 1029 int cmp = comparator.compare(e, getElement()); 1030 if (cmp > 0) { 1031 return (right == null) ? this : MoreObjects.firstNonNull(right.floor(comparator, e), this); 1032 } else if (cmp == 0) { 1033 return this; 1034 } else { 1035 return (left == null) ? null : left.floor(comparator, e); 1036 } 1037 } 1038 1039 @ParametricNullness 1040 E getElement() { 1041 // For discussion of this cast, see the comment on the elem field. 1042 return uncheckedCastNullableTToT(elem); 1043 } 1044 1045 int getCount() { 1046 return elemCount; 1047 } 1048 1049 @Override 1050 public String toString() { 1051 return Multisets.immutableEntry(getElement(), getCount()).toString(); 1052 } 1053 } 1054 1055 private static <T extends @Nullable Object> void successor(AvlNode<T> a, AvlNode<T> b) { 1056 a.succ = b; 1057 b.pred = a; 1058 } 1059 1060 private static <T extends @Nullable Object> void successor( 1061 AvlNode<T> a, AvlNode<T> b, AvlNode<T> c) { 1062 successor(a, b); 1063 successor(b, c); 1064 } 1065 1066 /* 1067 * TODO(jlevy): Decide whether entrySet() should return entries with an equals() method that 1068 * calls the comparator to compare the two keys. If that change is made, 1069 * AbstractMultiset.equals() can simply check whether two multisets have equal entry sets. 1070 */ 1071 1072 /** 1073 * @serialData the comparator, the number of distinct elements, the first element, its count, the 1074 * second element, its count, and so on 1075 */ 1076 @GwtIncompatible 1077 @J2ktIncompatible 1078 private void writeObject(ObjectOutputStream stream) throws IOException { 1079 stream.defaultWriteObject(); 1080 stream.writeObject(elementSet().comparator()); 1081 Serialization.writeMultiset(this, stream); 1082 } 1083 1084 @J2ktIncompatible 1085 @GwtIncompatible 1086 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 1087 stream.defaultReadObject(); 1088 @SuppressWarnings("unchecked") 1089 // reading data stored by writeObject 1090 Comparator<? super E> comparator = (Comparator<? super E>) requireNonNull(stream.readObject()); 1091 deserializationReplacement = new TreeMultiset<>(comparator); 1092 Serialization.populateMultiset(deserializationReplacement, stream); 1093 } 1094 1095 @J2ktIncompatible 1096 @GwtIncompatible 1097 private Object readResolve() { 1098 return requireNonNull(deserializationReplacement); // set by readObject 1099 } 1100 1101 @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 1; 1102}