
org.terracotta.offheapstore.util.AATreeSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of offheap-store Show documentation
Show all versions of offheap-store Show documentation
A library that offers data structures allocated off the java heap.
/*
* Copyright 2015 Terracotta, Inc., a Software AG company.
*
* 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 org.terracotta.offheapstore.util;
import java.util.AbstractSet;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.Stack;
public class AATreeSet> extends AbstractSet implements SortedSet {
private Node root = TerminalNode.terminal();
private int size = 0;
private boolean mutated;
private Node item = TerminalNode.terminal(), heir = TerminalNode.terminal();
private T removed;
@Override
public boolean add(T o) {
try {
root = insert(root, o);
if (mutated) {
size++;
}
return mutated;
} finally {
mutated = false;
}
}
@Override
@SuppressWarnings("unchecked")
public boolean remove(Object o) {
try {
root = remove(root, (T) o);
if (mutated) {
size--;
}
return mutated;
} finally {
heir = TerminalNode.terminal();
item = TerminalNode.terminal();
mutated = false;
removed = null;
}
}
@SuppressWarnings("unchecked")
public T removeAndReturn(Object o) {
try {
root = remove(root, (T) o);
if (mutated) {
size--;
}
return removed;
} finally {
heir = TerminalNode.terminal();
item = TerminalNode.terminal();
mutated = false;
removed = null;
}
}
@Override
public void clear() {
root = TerminalNode.terminal();
size = 0;
}
@Override
public Iterator iterator() {
return new TreeIterator();
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return root == TerminalNode.terminal();
}
@Override
public Comparator super T> comparator() {
return null;
}
@Override
public SortedSet subSet(T fromElement, T toElement) {
return new SubSet(fromElement, toElement);
}
@Override
public SortedSet headSet(T toElement) {
return new SubSet(null, toElement);
}
@Override
public SortedSet tailSet(T fromElement) {
return new SubSet(fromElement, null);
}
@Override
public T first() {
Node leftMost = root;
while (leftMost.getLeft() != TerminalNode.terminal()) {
leftMost = leftMost.getLeft();
}
return leftMost.getPayload();
}
@Override
public T last() {
Node rightMost = root;
while (rightMost.getRight() != TerminalNode.terminal()) {
rightMost = rightMost.getRight();
}
return rightMost.getPayload();
}
@SuppressWarnings("unchecked")
public T find(Object probe) {
return find(root, (T) probe).getPayload();
}
protected final Node getRoot() {
return root;
}
private Node find(Node top, T probe) {
if (top == TerminalNode.terminal()) {
return top;
} else {
int direction = top.getPayload().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 == TerminalNode.terminal()) {
mutated = true;
return createNode(data);
} else {
int direction = top.getPayload().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;
}
}
@SuppressWarnings("unchecked")
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 != TerminalNode.terminal()) {
int direction = top.getPayload().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 != TerminalNode.terminal() && item.getPayload().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;
}
public static interface Node> {
public void setLeft(Node node);
public void setRight(Node node);
public Node getLeft();
public Node getRight();
public int getLevel();
public void setLevel(int value);
public int decrementLevel();
public int incrementLevel();
public void swapPayload(Node with);
public E getPayload();
}
public static abstract class AbstractTreeNode> implements Node {
private Node left;
private Node right;
private int level;
public AbstractTreeNode() {
this(1);
}
private AbstractTreeNode(int level) {
this.left = TerminalNode.terminal();
this.right = TerminalNode.terminal();
this.level = level;
}
@Override
public void setLeft(Node node) {
left = node;
}
@Override
public void setRight(Node node) {
right = node;
}
@Override
public Node getLeft() {
return left;
}
@Override
public Node getRight() {
return right;
}
@Override
public int getLevel() {
return level;
}
@Override
public void setLevel(int value) {
level = value;
}
@Override
public int decrementLevel() {
return --level;
}
@Override
public int incrementLevel() {
return ++level;
}
}
private static final class TreeNode> extends AbstractTreeNode {
private E payload;
public TreeNode(E payload) {
super();
this.payload = payload;
}
@Override
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();
}
}
@Override
public E getPayload() {
return payload;
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static final class TerminalNode extends AbstractTreeNode {
private static final Node> TERMINAL = new TerminalNode();
public static > Node terminal() {
return (Node) TERMINAL;
}
private TerminalNode() {
super(0);
super.setLeft(this);
super.setRight(this);
}
@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();
}
@Override
public void swapPayload(Node payload) {
throw new AssertionError();
}
@Override
public Comparable getPayload() {
return null;
}
}
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
@SuppressWarnings("unchecked")
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);
} else {
throw new UnsupportedOperationException();
}
}
@Override
public int size() {
throw new UnsupportedOperationException();
}
@Override
public boolean isEmpty() {
return !iterator().hasNext();
}
@Override
public Comparator super T> comparator() {
return null;
}
@Override
public SortedSet subSet(T fromElement, T toElement) {
if (inRangeInclusive(fromElement) && inRangeInclusive(toElement)) {
return new SubSet(fromElement, toElement);
} else {
throw new IllegalArgumentException();
}
}
@Override
public SortedSet headSet(T toElement) {
if (inRangeInclusive(toElement)) {
return new SubSet(start, toElement);
} else {
throw new IllegalArgumentException();
}
}
@Override
public SortedSet tailSet(T fromElement) {
if (inRangeInclusive(fromElement)) {
return new SubSet(fromElement, end);
} else {
throw new IllegalArgumentException();
}
}
@Override
public T first() {
if (start == null) {
return AATreeSet.this.first();
} else {
throw new UnsupportedOperationException();
}
}
@Override
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);
}
}
class TreeIterator implements Iterator {
private final java.util.Stack> path = new Stack>();
private Node next;
TreeIterator() {
path.push(TerminalNode.terminal());
Node leftMost = root;
while (leftMost.getLeft() != TerminalNode.terminal()) {
path.push(leftMost);
leftMost = leftMost.getLeft();
}
next = leftMost;
}
TreeIterator(T start) {
path.push(TerminalNode.terminal());
Node current = root;
while (true) {
int direction = current.getPayload().compareTo(start);
if (direction > 0) {
if (current.getLeft() == TerminalNode.terminal()) {
next = current;
break;
} else {
path.push(current);
current = current.getLeft();
}
} else if (direction < 0) {
if (current.getRight() == TerminalNode.terminal()) {
next = path.pop();
break;
} else {
current = current.getRight();
}
} else {
next = current;
break;
}
}
}
@Override
public boolean hasNext() {
return next != TerminalNode.terminal();
}
@Override
public T next() {
Node current = next;
advance();
return current.getPayload();
}
private void advance() {
Node successor = next.getRight();
if (successor != TerminalNode.terminal()) {
while (successor.getLeft() != TerminalNode.terminal()) {
path.push(successor);
successor = successor.getLeft();
}
next = successor;
} else {
next = path.pop();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
class SubTreeIterator extends TreeIterator {
public SubTreeIterator(T start) {
super(start);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy