Пример #1
0
 @Override
 public SortedMultiset<E> tailMultiset(@Nullable E lowerBound, BoundType boundType) {
   return new TreeMultiset<E>(
       rootReference,
       range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)),
       header);
 }
Пример #2
0
 private long aggregateForEntries(Aggregate aggr) {
   AvlNode<E> root = rootReference.get();
   long total = aggr.treeAggregate(root);
   if (range.hasLowerBound()) {
     total -= aggregateBelowRange(aggr, root);
   }
   if (range.hasUpperBound()) {
     total -= aggregateAboveRange(aggr, root);
   }
   return total;
 }
Пример #3
0
 @Override
 public boolean equals(@Nullable Object obj) {
   if (obj instanceof GeneralRange) {
     GeneralRange<?> r = (GeneralRange<?>) obj;
     return comparator.equals(r.comparator)
         && hasLowerBound == r.hasLowerBound
         && hasUpperBound == r.hasUpperBound
         && getLowerBoundType().equals(r.getLowerBoundType())
         && getUpperBoundType().equals(r.getUpperBoundType())
         && Objects.equal(getLowerEndpoint(), r.getLowerEndpoint())
         && Objects.equal(getUpperEndpoint(), r.getUpperEndpoint());
   }
   return false;
 }
Пример #4
0
 @CanIgnoreReturnValue
 @Override
 public int remove(@Nullable Object element, int occurrences) {
   checkNonnegative(occurrences, "occurrences");
   if (occurrences == 0) {
     return count(element);
   }
   AvlNode<E> root = rootReference.get();
   int[] result = new int[1]; // used as a mutable int reference to hold result
   AvlNode<E> newRoot;
   try {
     @SuppressWarnings("unchecked")
     E e = (E) element;
     if (!range.contains(e) || root == null) {
       return 0;
     }
     newRoot = root.remove(comparator(), e, occurrences, result);
   } catch (ClassCastException e) {
     return 0;
   } catch (NullPointerException e) {
     return 0;
   }
   rootReference.checkAndSet(root, newRoot);
   return result[0];
 }
Пример #5
0
 TreeMultiset(Comparator<? super E> comparator) {
   super(comparator);
   this.range = GeneralRange.all(comparator);
   this.header = new AvlNode<E>(null, 1);
   successor(header, header);
   this.rootReference = new Reference<AvlNode<E>>();
 }
Пример #6
0
 /** Returns the same range relative to the reversed comparator. */
 GeneralRange<T> reverse() {
   GeneralRange<T> result = reverse;
   if (result == null) {
     result =
         new GeneralRange<T>(
             Ordering.from(comparator).reverse(),
             hasUpperBound,
             getUpperEndpoint(),
             getUpperBoundType(),
             hasLowerBound,
             getLowerEndpoint(),
             getLowerBoundType());
     result.reverse = this;
     return this.reverse = result;
   }
   return result;
 }
Пример #7
0
 @Nullable
 private AvlNode<E> lastNode() {
   AvlNode<E> root = rootReference.get();
   if (root == null) {
     return null;
   }
   AvlNode<E> node;
   if (range.hasUpperBound()) {
     E endpoint = range.getUpperEndpoint();
     node = rootReference.get().floor(comparator(), endpoint);
     if (node == null) {
       return null;
     }
     if (range.getUpperBoundType() == BoundType.OPEN
         && comparator().compare(endpoint, node.getElement()) == 0) {
       node = node.pred;
     }
   } else {
     node = header.pred;
   }
   return (node == header || !range.contains(node.getElement())) ? null : node;
 }
Пример #8
0
 private long aggregateAboveRange(Aggregate aggr, @Nullable AvlNode<E> node) {
   if (node == null) {
     return 0;
   }
   int cmp = comparator().compare(range.getUpperEndpoint(), node.elem);
   if (cmp > 0) {
     return aggregateAboveRange(aggr, node.right);
   } else if (cmp == 0) {
     switch (range.getUpperBoundType()) {
       case OPEN:
         return aggr.nodeAggregate(node) + aggr.treeAggregate(node.right);
       case CLOSED:
         return aggr.treeAggregate(node.right);
       default:
         throw new AssertionError();
     }
   } else {
     return aggr.treeAggregate(node.right)
         + aggr.nodeAggregate(node)
         + aggregateAboveRange(aggr, node.left);
   }
 }
Пример #9
0
 @GwtIncompatible // java.io.ObjectInputStream
 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
   stream.defaultReadObject();
   @SuppressWarnings("unchecked")
   // reading data stored by writeObject
   Comparator<? super E> comparator = (Comparator<? super E>) stream.readObject();
   Serialization.getFieldSetter(AbstractSortedMultiset.class, "comparator").set(this, comparator);
   Serialization.getFieldSetter(TreeMultiset.class, "range")
       .set(this, GeneralRange.all(comparator));
   Serialization.getFieldSetter(TreeMultiset.class, "rootReference")
       .set(this, new Reference<AvlNode<E>>());
   AvlNode<E> header = new AvlNode<E>(null, 1);
   Serialization.getFieldSetter(TreeMultiset.class, "header").set(this, header);
   successor(header, header);
   Serialization.populateMultiset(this, stream);
 }
Пример #10
0
 @Override
 public int count(@Nullable Object element) {
   try {
     @SuppressWarnings("unchecked")
     E e = (E) element;
     AvlNode<E> root = rootReference.get();
     if (!range.contains(e) || root == null) {
       return 0;
     }
     return root.count(comparator(), e);
   } catch (ClassCastException e) {
     return 0;
   } catch (NullPointerException e) {
     return 0;
   }
 }
Пример #11
0
  @CanIgnoreReturnValue
  @Override
  public int setCount(@Nullable E element, int count) {
    checkNonnegative(count, "count");
    if (!range.contains(element)) {
      checkArgument(count == 0);
      return 0;
    }

    AvlNode<E> root = rootReference.get();
    if (root == null) {
      if (count > 0) {
        add(element, count);
      }
      return 0;
    }
    int[] result = new int[1]; // used as a mutable int reference to hold result
    AvlNode<E> newRoot = root.setCount(comparator(), element, count, result);
    rootReference.checkAndSet(root, newRoot);
    return result[0];
  }
Пример #12
0
 @CanIgnoreReturnValue
 @Override
 public int add(@Nullable E element, int occurrences) {
   checkNonnegative(occurrences, "occurrences");
   if (occurrences == 0) {
     return count(element);
   }
   checkArgument(range.contains(element));
   AvlNode<E> root = rootReference.get();
   if (root == null) {
     comparator().compare(element, element);
     AvlNode<E> newRoot = new AvlNode<E>(element, occurrences);
     successor(header, newRoot, header);
     rootReference.checkAndSet(root, newRoot);
     return 0;
   }
   int[] result = new int[1]; // used as a mutable int reference to hold result
   AvlNode<E> newRoot = root.add(comparator(), element, occurrences, result);
   rootReference.checkAndSet(root, newRoot);
   return result[0];
 }
Пример #13
0
  @CanIgnoreReturnValue
  @Override
  public boolean setCount(@Nullable E element, int oldCount, int newCount) {
    checkNonnegative(newCount, "newCount");
    checkNonnegative(oldCount, "oldCount");
    checkArgument(range.contains(element));

    AvlNode<E> root = rootReference.get();
    if (root == null) {
      if (oldCount == 0) {
        if (newCount > 0) {
          add(element, newCount);
        }
        return true;
      } else {
        return false;
      }
    }
    int[] result = new int[1]; // used as a mutable int reference to hold result
    AvlNode<E> newRoot = root.setCount(comparator(), element, oldCount, newCount, result);
    rootReference.checkAndSet(root, newRoot);
    return result[0] == oldCount;
  }
Пример #14
0
 TreeMultiset(Reference<AvlNode<E>> rootReference, GeneralRange<E> range, AvlNode<E> endLink) {
   super(range.comparator());
   this.rootReference = rootReference;
   this.range = range;
   this.header = endLink;
 }
Пример #15
0
  /**
   * Returns the intersection of the two ranges, or an empty range if their intersection is empty.
   */
  GeneralRange<T> intersect(GeneralRange<T> other) {
    checkNotNull(other);
    checkArgument(comparator.equals(other.comparator));

    boolean hasLowBound = this.hasLowerBound;
    @Nullable T lowEnd = getLowerEndpoint();
    BoundType lowType = getLowerBoundType();
    if (!hasLowerBound()) {
      hasLowBound = other.hasLowerBound;
      lowEnd = other.getLowerEndpoint();
      lowType = other.getLowerBoundType();
    } else if (other.hasLowerBound()) {
      int cmp = comparator.compare(getLowerEndpoint(), other.getLowerEndpoint());
      if (cmp < 0 || (cmp == 0 && other.getLowerBoundType() == OPEN)) {
        lowEnd = other.getLowerEndpoint();
        lowType = other.getLowerBoundType();
      }
    }

    boolean hasUpBound = this.hasUpperBound;
    @Nullable T upEnd = getUpperEndpoint();
    BoundType upType = getUpperBoundType();
    if (!hasUpperBound()) {
      hasUpBound = other.hasUpperBound;
      upEnd = other.getUpperEndpoint();
      upType = other.getUpperBoundType();
    } else if (other.hasUpperBound()) {
      int cmp = comparator.compare(getUpperEndpoint(), other.getUpperEndpoint());
      if (cmp > 0 || (cmp == 0 && other.getUpperBoundType() == OPEN)) {
        upEnd = other.getUpperEndpoint();
        upType = other.getUpperBoundType();
      }
    }

    if (hasLowBound && hasUpBound) {
      int cmp = comparator.compare(lowEnd, upEnd);
      if (cmp > 0 || (cmp == 0 && lowType == OPEN && upType == OPEN)) {
        // force allowed empty range
        lowEnd = upEnd;
        lowType = OPEN;
        upType = CLOSED;
      }
    }

    return new GeneralRange<T>(comparator, hasLowBound, lowEnd, lowType, hasUpBound, upEnd, upType);
  }