Refine search
private @Nullable 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; }
@Override public SortedMultiset<E> tailMultiset(@Nullable E lowerBound, BoundType boundType) { return new TreeMultiset<E>( rootReference, range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)), header); }
boolean isEmpty() { return (hasUpperBound() && tooLow(getUpperEndpoint())) || (hasLowerBound() && tooHigh(getLowerEndpoint())); }
boolean tooLow(@Nullable T t) { if (!hasLowerBound()) { return false; } T lbound = getLowerEndpoint(); int cmp = comparator.compare(t, lbound); return cmp < 0 | (cmp == 0 & getLowerBoundType() == OPEN); }
/** 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; }
@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]; }
@Override public SortedMultiset<E> headMultiset(@Nullable E upperBound, BoundType boundType) { return new TreeMultiset<E>( rootReference, range.intersect(GeneralRange.upTo(comparator(), upperBound, boundType)), header); }
@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; } }
boolean tooLow(@Nullable T t) { if (!hasLowerBound()) { return false; } T lbound = lowerEndpoint; int cmp = comparator.compare(t, lbound); return cmp < 0 | (cmp == 0 & lowerBoundType == OPEN); }
@Override public int count(@Nullable Object element) { try { E e = checkElement(element); if (range.contains(e)) { Node<E> node = BstOperations.seek(comparator(), rootReference.get(), e); return countOrZero(node); } return 0; } catch (ClassCastException e) { return 0; } catch (NullPointerException e) { return 0; } }
/** Returns the first node in the tree that is in range. */ private @Nullable AvlNode<E> firstNode() { AvlNode<E> root = rootReference.get(); if (root == null) { return null; } AvlNode<E> node; if (range.hasLowerBound()) { E endpoint = range.getLowerEndpoint(); node = rootReference.get().ceiling(comparator(), endpoint); if (node == null) { return null; } if (range.getLowerBoundType() == BoundType.OPEN && comparator().compare(endpoint, node.getElement()) == 0) { node = node.succ; } } else { node = header.succ; } return (node == header || !range.contains(node.getElement())) ? null : node; }
checkArgument(comparator.equals(other.comparator)); @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(); @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(); return new GeneralRange<T>(comparator, hasLowBound, lowEnd, lowType, hasUpBound, upEnd, upType);
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; }
public void testLowerRange() { for (BoundType lBoundType : BoundType.values()) { GeneralRange<Integer> range = GeneralRange.downTo(ORDERING, 3, lBoundType); for (Integer i : IN_ORDER_VALUES) { assertEquals( ORDERING.compare(i, 3) > 0 || (ORDERING.compare(i, 3) == 0 && lBoundType == CLOSED), range.contains(i)); assertEquals( ORDERING.compare(i, 3) < 0 || (ORDERING.compare(i, 3) == 0 && lBoundType == OPEN), range.tooLow(i)); assertFalse(range.tooHigh(i)); } } }
@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]; }
public void testUpperRange() { for (BoundType lBoundType : BoundType.values()) { GeneralRange<Integer> range = GeneralRange.upTo(ORDERING, 3, lBoundType); for (Integer i : IN_ORDER_VALUES) { assertEquals( ORDERING.compare(i, 3) < 0 || (ORDERING.compare(i, 3) == 0 && lBoundType == CLOSED), range.contains(i)); assertEquals( ORDERING.compare(i, 3) > 0 || (ORDERING.compare(i, 3) == 0 && lBoundType == OPEN), range.tooHigh(i)); assertFalse(range.tooLow(i)); } } }
@Override public void clear() { if (!range.hasLowerBound() && !range.hasUpperBound()) { // We can do this in O(n) rather than removing one by one, which could force rebalancing. for (AvlNode<E> current = header.succ; current != header; ) { AvlNode<E> next = current.succ; current.elemCount = 0; // Also clear these fields so that one deleted Entry doesn't retain all elements. current.left = null; current.right = null; current.pred = null; current.succ = null; current = next; } successor(header, header); rootReference.clear(); } else { // TODO(cpovirk): Perhaps we can optimize in this case, too? Iterators.clear(entryIterator()); } }
public void testReverse() { assertEquals(GeneralRange.all(ORDERING.reverse()), GeneralRange.all(ORDERING).reverse()); assertEquals( GeneralRange.downTo(ORDERING.reverse(), 3, CLOSED), GeneralRange.upTo(ORDERING, 3, CLOSED).reverse()); assertEquals( GeneralRange.upTo(ORDERING.reverse(), 3, OPEN), GeneralRange.downTo(ORDERING, 3, OPEN).reverse()); assertEquals( GeneralRange.range(ORDERING.reverse(), 5, OPEN, 3, CLOSED), GeneralRange.range(ORDERING, 3, CLOSED, 5, OPEN).reverse()); }