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}