
net.sf.ehcache.store.disk.ods.AATreeSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
/**
* Copyright Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.ehcache.store.disk.ods;
import java.util.AbstractSet;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.Stack;
/**
* A AA-Tree based SortedSet implementation
*
* @param type of values stored
*
* @author Chris Dennis
*/
public class AATreeSet extends AbstractSet implements SortedSet {
private static final Node> TERMINAL = new TerminalNode();
private Node root = terminal();
private int size;
private boolean mutated;
private Node item = terminal();
private Node heir = terminal();
private T removed;
@Override
public boolean add(T o) {
try {
root = insert(root, o);
if (mutated) {
size++;
}
return mutated;
} finally {
mutated = false;
}
}
@Override
public boolean remove(Object o) {
try {
root = remove(root, (T) o);
if (mutated) {
size--;
}
return mutated;
} finally {
heir = terminal();
item = terminal();
mutated = false;
removed = null;
}
}
/**
* Remove the node matching this object and return it.
*/
public T removeAndReturn(Object o) {
try {
root = remove(root, (T) o);
if (mutated) {
size--;
}
return removed;
} finally {
heir = terminal();
item = terminal();
mutated = false;
removed = null;
}
}
@Override
public void clear() {
root = terminal();
size = 0;
}
@Override
public Iterator iterator() {
return new TreeIterator();
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return root == terminal();
}
/**
* {@inheritDoc}
*/
public Comparator super T> comparator() {
return null;
}
/**
* {@inheritDoc}
*/
public SortedSet subSet(T fromElement, T toElement) {
return new SubSet(fromElement, toElement);
}
/**
* {@inheritDoc}
*/
public SortedSet headSet(T toElement) {
return new SubSet(null, toElement);
}
/**
* {@inheritDoc}
*/
public SortedSet tailSet(T fromElement) {
return new SubSet(fromElement, null);
}
/**
* {@inheritDoc}
*/
public T first() {
Node leftMost = root;
while (leftMost.getLeft() != terminal()) {
leftMost = leftMost.getLeft();
}
return leftMost.getPayload();
}
/**
* {@inheritDoc}
*/
public T last() {
Node rightMost = root;
while (rightMost.getRight() != terminal()) {
rightMost = rightMost.getRight();
}
return rightMost.getPayload();
}
/**
* Find the node within this tree equal to the probe node.
*/
public T find(Object probe) {
return find(root, (T) probe).getPayload();
}
private Node terminal() {
return (Node) TERMINAL;
}
/**
* Returns the root node of this tree.
*/
protected final Node getRoot() {
return root;
}
private Node find(Node top, T probe) {
if (top == terminal()) {
return top;
} else {
int direction = top.compareTo(probe);
if (direction > 0) {
return find(top.getLeft(), probe);
} else if (direction < 0) {
return find(top.getRight(), probe);
} else {
return top;
}
}
}
private Node insert(Node top, T data) {
if (top == terminal()) {
mutated = true;
return createNode(data);
} else {
int direction = top.compareTo(data);
if (direction > 0) {
top.setLeft(insert(top.getLeft(), data));
} else if (direction < 0) {
top.setRight(insert(top.getRight(), data));
} else {
return top;
}
top = skew(top);
top = split(top);
return top;
}
}
private Node createNode(T data) {
if (data instanceof Node>) {
return (Node) data;
} else {
return new TreeNode(data);
}
}
private Node remove(Node top, T data) {
if (top != terminal()) {
int direction = top.compareTo(data);
heir = top;
if (direction > 0) {
top.setLeft(remove(top.getLeft(), data));
} else {
item = top;
top.setRight(remove(top.getRight(), data));
}
if (top == heir) {
if (item != terminal() && item.compareTo(data) == 0) {
mutated = true;
item.swapPayload(top);
removed = top.getPayload();
top = top.getRight();
}
} else {
if (top.getLeft().getLevel() < top.getLevel() - 1 || top.getRight().getLevel() < top.getLevel() - 1) {
if (top.getRight().getLevel() > top.decrementLevel()) {
top.getRight().setLevel(top.getLevel());
}
top = skew(top);
top.setRight(skew(top.getRight()));
top.getRight().setRight(skew(top.getRight().getRight()));
top = split(top);
top.setRight(split(top.getRight()));
}
}
}
return top;
}
private static Node skew(Node top) {
if (top.getLeft().getLevel() == top.getLevel() && top.getLevel() != 0) {
Node save = top.getLeft();
top.setLeft(save.getRight());
save.setRight(top);
top = save;
}
return top;
}
private static Node split(Node top) {
if (top.getRight().getRight().getLevel() == top.getLevel() && top.getLevel() != 0) {
Node save = top.getRight();
top.setRight(save.getLeft());
save.setLeft(top);
top = save;
top.incrementLevel();
}
return top;
}
/**
* Interface implemented by nodes within this tree.
*/
public static interface Node {
/**
* Compare this node to the supplied 'data' object.
*/
public int compareTo(E data);
/**
* Set this node's left child.
*/
public void setLeft(Node node);
/**
* Set this node's right child.
*/
public void setRight(Node node);
/**
* Get this node's left child.
*/
public Node getLeft();
/**
* Get this node's right child.
*/
public Node getRight();
/**
* Get this node's level.
*/
public int getLevel();
/**
* Set this node's level.
*/
public void setLevel(int value);
/**
* Decrement and then return this node's new level.
*/
public int decrementLevel();
/**
* Increment and then return this node's new level.
*/
public int incrementLevel();
/**
* Swap the payload objects between this node and the supplied node.
*/
public void swapPayload(Node with);
/**
* Return the 'value' object held within this node.
*/
public E getPayload();
}
/**
* Abstract node implementation that can be extended with a custom payload.
*/
public abstract static class AbstractTreeNode implements Node {
private Node left;
private Node right;
private int level;
/**
* Constructs an initial (leaf) node.
*/
public AbstractTreeNode() {
this(1);
}
private AbstractTreeNode(int level) {
this.left = (Node) TERMINAL;
this.right = (Node) TERMINAL;
this.level = level;
}
/**
* {@inheritDoc}
*/
public void setLeft(Node node) {
left = node;
}
/**
* {@inheritDoc}
*/
public void setRight(Node node) {
right = node;
}
/**
* {@inheritDoc}
*/
public Node getLeft() {
return left;
}
/**
* {@inheritDoc}
*/
public Node getRight() {
return right;
}
/**
* {@inheritDoc}
*/
public int getLevel() {
return level;
}
/**
* {@inheritDoc}
*/
public void setLevel(int value) {
level = value;
}
/**
* {@inheritDoc}
*/
public int decrementLevel() {
return --level;
}
/**
* {@inheritDoc}
*/
public int incrementLevel() {
return ++level;
}
}
/**
* Default Comparable wrapping node implementation.
*/
private static final class TreeNode extends AbstractTreeNode {
private E payload;
public TreeNode(E payload) {
super();
this.payload = payload;
}
public int compareTo(E data) {
return payload.compareTo(data);
}
public void swapPayload(Node node) {
if (node instanceof TreeNode>) {
TreeNode treeNode = (TreeNode) node;
E temp = treeNode.payload;
treeNode.payload = this.payload;
this.payload = temp;
} else {
throw new IllegalArgumentException();
}
}
public E getPayload() {
return payload;
}
}
/**
* Node implementation that is used to mark the terminal (leaf) nodes of the tree.
*/
private static final class TerminalNode extends AbstractTreeNode {
TerminalNode() {
super(0);
super.setLeft(this);
super.setRight(this);
}
public int compareTo(E data) {
return 0;
}
@Override
public void setLeft(Node right) {
if (right != TERMINAL) {
throw new AssertionError();
}
}
@Override
public void setRight(Node left) {
if (left != TERMINAL) {
throw new AssertionError();
}
}
@Override
public void setLevel(int value) {
throw new AssertionError();
}
@Override
public int decrementLevel() {
throw new AssertionError();
}
@Override
public int incrementLevel() {
throw new AssertionError();
}
public void swapPayload(Node payload) {
throw new AssertionError();
}
public E getPayload() {
return null;
}
}
/**
* SortedSet representation of a range of the tree.
*/
private class SubSet extends AbstractSet implements SortedSet {
private final T start;
private final T end;
SubSet(T start, T end) {
this.start = start;
this.end = end;
}
@Override
public boolean add(T o) {
if (inRange(o)) {
return AATreeSet.this.add(o);
} else {
throw new IllegalArgumentException();
}
}
@Override
public boolean remove(Object o) {
if (inRange((T) o)) {
return remove(o);
} else {
return false;
}
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public Iterator iterator() {
if (end == null) {
return new SubTreeIterator(start, end);
} else {
throw new UnsupportedOperationException();
}
}
@Override
public int size() {
throw new UnsupportedOperationException();
}
@Override
public boolean isEmpty() {
return !iterator().hasNext();
}
public Comparator super T> comparator() {
return null;
}
public SortedSet subSet(T fromElement, T toElement) {
if (inRangeInclusive(fromElement) && inRangeInclusive(toElement)) {
return new SubSet(fromElement, toElement);
} else {
throw new IllegalArgumentException();
}
}
public SortedSet headSet(T toElement) {
if (inRangeInclusive(toElement)) {
return new SubSet(start, toElement);
} else {
throw new IllegalArgumentException();
}
}
public SortedSet tailSet(T fromElement) {
if (inRangeInclusive(fromElement)) {
return new SubSet(fromElement, end);
} else {
throw new IllegalArgumentException();
}
}
public T first() {
if (start == null) {
return AATreeSet.this.first();
} else {
throw new UnsupportedOperationException();
}
}
public T last() {
if (end == null) {
return AATreeSet.this.last();
} else {
throw new UnsupportedOperationException();
}
}
private boolean inRange(T value) {
return (start == null || start.compareTo(value) <= 0) && (end == null || end.compareTo(value) > 0);
}
private boolean inRangeInclusive(T value) {
return (start == null || start.compareTo(value) <= 0) && (end == null || end.compareTo(value) >= 0);
}
}
/**
* Iterator that iterates over the tree.
*/
private class TreeIterator implements Iterator {
private final Stack> path = new Stack>();
private Node next;
TreeIterator() {
path.push(terminal());
Node leftMost = root;
while (leftMost.getLeft() != terminal()) {
path.push(leftMost);
leftMost = leftMost.getLeft();
}
next = leftMost;
}
TreeIterator(T start) {
path.push(terminal());
Node current = root;
while (true) {
int direction = current.compareTo(start);
if (direction > 0) {
if (current.getLeft() == terminal()) {
next = current;
break;
} else {
path.push(current);
current = current.getLeft();
}
} else if (direction < 0) {
if (current.getRight() == terminal()) {
next = path.pop();
break;
} else {
current = current.getRight();
}
} else {
next = current;
break;
}
}
}
public boolean hasNext() {
return next != terminal();
}
public T next() {
Node current = next;
advance();
return current.getPayload();
}
private void advance() {
Node successor = next.getRight();
if (successor != terminal()) {
while (successor.getLeft() != terminal()) {
path.push(successor);
successor = successor.getLeft();
}
next = successor;
} else {
next = path.pop();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
/**
* Iterator that iterates over a subset of the tree.
*/
private class SubTreeIterator extends TreeIterator {
SubTreeIterator(T start, T end) {
super(start);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy