Adds generalization of TreeMap to further enable the full support of

NavigableMap
This commit is contained in:
konsoletyper 2014-04-02 13:47:37 +04:00
parent 05569f4eef
commit 3dc42b95f5

View File

@ -78,11 +78,20 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
size += right.size; size += right.size;
} }
} }
public TreeNode<K, V> forward(boolean reverse) {
return !reverse ? left : right;
}
public TreeNode<K, V> down(boolean reverse) {
return !reverse ? right : left;
}
} }
TreeNode<K, V> root; TreeNode<K, V> root;
private TComparator<? super K> comparator; private TComparator<? super K> comparator;
private TComparator<? super K> originalComparator; private TComparator<? super K> originalComparator;
private TComparator<? super K> revertedComparator;
private int modCount = 0; private int modCount = 0;
private EntrySet<K, V> cachedEntrySet; private EntrySet<K, V> cachedEntrySet;
@ -124,6 +133,16 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
fillMap(entries); fillMap(entries);
} }
private void ensureRevertedComparator() {
if (revertedComparator == null) {
revertedComparator = new TComparator<K>() {
@Override public int compare(K o1, K o2) {
return -originalComparator.compare(o1, o2);
}
};
}
}
private void fillMap(Entry<? extends K, ? extends V>[] entries) { private void fillMap(Entry<? extends K, ? extends V>[] entries) {
root = createNode(entries, 0, entries.length - 1); root = createNode(entries, 0, entries.length - 1);
} }
@ -201,25 +220,28 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
return null; return null;
} }
TreeNode<K, V> findExactOrNext(Object key) { TreeNode<K, V> findExactOrNext(Object key, boolean reverse) {
TreeNode<K, V> node = root; TreeNode<K, V> node = root;
TreeNode<K, V> lastLeftTurn = null; TreeNode<K, V> lastForward = null;
while (node != null) { while (node != null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
int cmp = comparator.compare((K)key, node.getKey()); int cmp = comparator.compare((K)key, node.getKey());
if (reverse) {
cmp = -cmp;
}
if (cmp == 0) { if (cmp == 0) {
return node; return node;
} else if (cmp < 0) { } else if (cmp < 0) {
lastLeftTurn = node; lastForward = node;
node = node.left; node = node.forward(reverse);
} else { } else {
node = node.right; node = node.down(reverse);
} }
} }
return lastLeftTurn; return lastForward;
} }
TreeNode<K, V>[] pathToExactOrNext(Object key) { TreeNode<K, V>[] pathToExactOrNext(Object key, boolean reverse) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
TreeNode<K, V>[] path = (TreeNode<K, V>[])new TreeNode<?, ?>[height()]; TreeNode<K, V>[] path = (TreeNode<K, V>[])new TreeNode<?, ?>[height()];
int depth = 0; int depth = 0;
@ -227,36 +249,42 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
while (node != null) { while (node != null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
int cmp = comparator.compare((K)key, node.getKey()); int cmp = comparator.compare((K)key, node.getKey());
if (reverse) {
cmp = -cmp;
}
if (cmp == 0) { if (cmp == 0) {
path[depth++] = node; path[depth++] = node;
break; break;
} else if (cmp < 0) { } else if (cmp < 0) {
path[depth++] = node; path[depth++] = node;
node = node.left; node = node.forward(reverse);
} else { } else {
node = node.right; node = node.down(reverse);
} }
} }
return TArrays.copyOf(path, depth); return TArrays.copyOf(path, depth);
} }
TreeNode<K, V> findNext(Object key) { TreeNode<K, V> findNext(Object key, boolean reverse) {
TreeNode<K, V> node = root; TreeNode<K, V> node = root;
TreeNode<K, V> lastLeftTurn = null; TreeNode<K, V> lastForward = null;
while (node != null) { while (node != null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
int cmp = comparator.compare((K)key, node.getKey()); int cmp = comparator.compare((K)key, node.getKey());
if (reverse) {
cmp = -cmp;
}
if (cmp < 0) { if (cmp < 0) {
lastLeftTurn = node; lastForward = node;
node = node.left; node = node.forward(reverse);
} else { } else {
node = node.right; node = node.down(reverse);
} }
} }
return lastLeftTurn; return lastForward;
} }
TreeNode<K, V>[] pathToNext(Object key) { TreeNode<K, V>[] pathToNext(Object key, boolean reverse) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
TreeNode<K, V>[] path = (TreeNode<K, V>[])new TreeNode<?, ?>[height()]; TreeNode<K, V>[] path = (TreeNode<K, V>[])new TreeNode<?, ?>[height()];
int depth = 0; int depth = 0;
@ -264,97 +292,27 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
while (node != null) { while (node != null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
int cmp = comparator.compare((K)key, node.getKey()); int cmp = comparator.compare((K)key, node.getKey());
if (reverse) {
cmp = -cmp;
}
if (cmp < 0) { if (cmp < 0) {
path[depth++] = node; path[depth++] = node;
node = node.left; node = node.forward(reverse);
} else { } else {
node = node.right; node = node.down(reverse);
} }
} }
return TArrays.copyOf(path, depth); return TArrays.copyOf(path, depth);
} }
TreeNode<K, V> findExactOrPrev(Object key) { TreeNode<K, V>[] pathToFirst(boolean reverse) {
TreeNode<K, V> node = root;
TreeNode<K, V> lastRightTurn = null;
while (node != null) {
@SuppressWarnings("unchecked")
int cmp = comparator.compare((K)key, node.getKey());
if (cmp == 0) {
return node;
} else if (cmp > 0) {
lastRightTurn = node;
node = node.right;
} else {
node = node.left;
}
}
return lastRightTurn;
}
TreeNode<K, V>[] pathToExactOrPrev(Object key) {
@SuppressWarnings("unchecked")
TreeNode<K, V>[] path = (TreeNode<K, V>[])new TreeNode<?, ?>[height()];
int depth = 0;
TreeNode<K, V> node = root;
while (node != null) {
@SuppressWarnings("unchecked")
int cmp = comparator.compare((K)key, node.getKey());
if (cmp == 0) {
path[depth++] = node;
break;
} else if (cmp > 0) {
path[depth++] = node;
node = node.right;
} else {
node = node.left;
}
}
return TArrays.copyOf(path, depth);
}
TreeNode<K, V>[] pathToFirst() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
TreeNode<K, V>[] path = (TreeNode<K, V>[])new TreeNode<?, ?>[height()]; TreeNode<K, V>[] path = (TreeNode<K, V>[])new TreeNode<?, ?>[height()];
int depth = 0; int depth = 0;
TreeNode<K, V> node = root; TreeNode<K, V> node = root;
while (node != null) { while (node != null) {
path[depth++] = node; path[depth++] = node;
node = node.left; node = node.forward(reverse);
}
return TArrays.copyOf(path, depth);
}
TreeNode<K, V> findPrev(Object key) {
TreeNode<K, V> node = root;
TreeNode<K, V> lastRightTurn = null;
while (node != null) {
@SuppressWarnings("unchecked")
int cmp = comparator.compare((K)key, node.getKey());
if (cmp > 0) {
lastRightTurn = node;
node = node.right;
} else {
node = node.left;
}
}
return lastRightTurn;
}
TreeNode<K, V>[] pathToPrev(Object key) {
@SuppressWarnings("unchecked")
TreeNode<K, V>[] path = (TreeNode<K, V>[])new TreeNode<?, ?>[height()];
int depth = 0;
TreeNode<K, V> node = root;
while (node != null) {
@SuppressWarnings("unchecked")
int cmp = comparator.compare((K)key, node.getKey());
if (cmp > 0) {
path[depth++] = node;
node = node.right;
} else {
node = node.left;
}
} }
return TArrays.copyOf(path, depth); return TArrays.copyOf(path, depth);
} }
@ -415,7 +373,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
@Override @Override
public TSet<Entry<K, V>> entrySet() { public TSet<Entry<K, V>> entrySet() {
if (cachedEntrySet == null) { if (cachedEntrySet == null) {
cachedEntrySet = new EntrySet<>(this, null, true, false, null, true, false); cachedEntrySet = new EntrySet<>(this, null, true, false, null, true, false, false);
} }
return cachedEntrySet; return cachedEntrySet;
} }
@ -430,22 +388,22 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
if (comparator.compare(fromKey, toKey) > 0) { if (comparator.compare(fromKey, toKey) > 0) {
throw new TIllegalArgumentException(); throw new TIllegalArgumentException();
} }
return new SubMap<>(this, fromKey, true, true, toKey, false, true); return new MapView<>(this, fromKey, true, true, toKey, false, true, false);
} }
@Override @Override
public TSortedMap<K, V> headMap(K toKey) { public TSortedMap<K, V> headMap(K toKey) {
return new SubMap<>(this, null, true, false, toKey, false, true); return new MapView<>(this, null, true, false, toKey, false, true, false);
} }
@Override @Override
public TSortedMap<K, V> tailMap(K fromKey) { public TSortedMap<K, V> tailMap(K fromKey) {
return new SubMap<>(this, fromKey, true, true, null, false, false); return new MapView<>(this, fromKey, true, true, null, false, false, false);
} }
@Override @Override
public K firstKey() { public K firstKey() {
TreeNode<K, V> node = firstNode(); TreeNode<K, V> node = firstNode(false);
if (node == null) { if (node == null) {
throw new TNoSuchElementException(); throw new TNoSuchElementException();
} }
@ -454,29 +412,19 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
@Override @Override
public K lastKey() { public K lastKey() {
TreeNode<K, V> node = lastNode(); TreeNode<K, V> node = firstNode(true);
if (node == null) { if (node == null) {
throw new TNoSuchElementException(); throw new TNoSuchElementException();
} }
return node.getKey(); return node.getKey();
} }
private TreeNode<K, V> firstNode() { private TreeNode<K, V> firstNode(boolean reverse) {
TreeNode<K, V> node = root; TreeNode<K, V> node = root;
TreeNode<K, V> prev = null; TreeNode<K, V> prev = null;
while (node != null) { while (node != null) {
prev = node; prev = node;
node = node.left; node = node.forward(reverse);
}
return prev;
}
private TreeNode<K, V> lastNode() {
TreeNode<K, V> node = root;
TreeNode<K, V> prev = null;
while (node != null) {
prev = node;
node = node.right;
} }
return prev; return prev;
} }
@ -507,9 +455,10 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
private boolean toIncluded; private boolean toIncluded;
private boolean toChecked; private boolean toChecked;
private int cachedSize; private int cachedSize;
private boolean reverse;
public EntrySet(TTreeMap<K, V> owner, K from, boolean fromIncluded, boolean fromChecked, public EntrySet(TTreeMap<K, V> owner, K from, boolean fromIncluded, boolean fromChecked,
K to, boolean toIncluded, boolean toChecked) { K to, boolean toIncluded, boolean toChecked, boolean reverse) {
this.owner = owner; this.owner = owner;
this.from = from; this.from = from;
this.fromIncluded = fromIncluded; this.fromIncluded = fromIncluded;
@ -517,6 +466,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
this.to = to; this.to = to;
this.toIncluded = toIncluded; this.toIncluded = toIncluded;
this.toChecked = toChecked; this.toChecked = toChecked;
this.reverse = reverse;
} }
@Override @Override
@ -526,7 +476,8 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
modCount = owner.modCount; modCount = owner.modCount;
size = owner.size(); size = owner.size();
if (fromChecked) { if (fromChecked) {
TreeNode<K, V>[] path = fromIncluded ? owner.pathToPrev(from) : owner.pathToExactOrPrev(from); TreeNode<K, V>[] path = fromIncluded ? owner.pathToNext(from, true) :
owner.pathToExactOrNext(from, true);
for (TreeNode<K, V> node : path) { for (TreeNode<K, V> node : path) {
if (node.left != null) { if (node.left != null) {
size -= node.left.size; size -= node.left.size;
@ -535,7 +486,8 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
size -= path.length; size -= path.length;
} }
if (toChecked) { if (toChecked) {
TreeNode<K, V> path[] = toIncluded ? owner.pathToNext(to) : owner.pathToExactOrNext(to); TreeNode<K, V> path[] = toIncluded ? owner.pathToNext(to, false) :
owner.pathToExactOrNext(to, false);
for (TreeNode<K, V> node : path) { for (TreeNode<K, V> node : path) {
if (node.right != null) { if (node.right != null) {
size -= node.right.size; size -= node.right.size;
@ -551,18 +503,20 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
@Override @Override
public TIterator<Entry<K, V>> iterator() { public TIterator<Entry<K, V>> iterator() {
TreeNode<K, V>[] fromPath; TreeNode<K, V>[] fromPath;
K from = !reverse ? this.from : this.to;
K to = !reverse ? this.to : this.from;
if (fromChecked) { if (fromChecked) {
fromPath = fromIncluded ? owner.pathToExactOrNext(from) : owner.pathToNext(from); fromPath = fromIncluded ? owner.pathToExactOrNext(from, reverse) : owner.pathToNext(from, reverse);
} else { } else {
fromPath = owner.pathToFirst(); fromPath = owner.pathToFirst(reverse);
} }
TreeNode<K, V> toEntry; TreeNode<K, V> toEntry;
if (toChecked) { if (toChecked) {
toEntry = toIncluded ? owner.findExactOrPrev(to) : owner.findPrev(to); toEntry = toIncluded ? owner.findExactOrNext(to, !reverse) : owner.findNext(to, !reverse);
} else { } else {
toEntry = owner.lastNode(); toEntry = owner.firstNode(!reverse);
} }
return new EntryIterator<>(owner, fromPath, toEntry); return new EntryIterator<>(owner, fromPath, toEntry, reverse);
} }
@Override @Override
@ -603,13 +557,15 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
private TreeNode<K, V> last; private TreeNode<K, V> last;
private TreeNode<K, V> to; private TreeNode<K, V> to;
private int depth; private int depth;
private boolean reverse;
public EntryIterator(TTreeMap<K, V> owner, TreeNode<K, V>[] path, TreeNode<K, V> to) { public EntryIterator(TTreeMap<K, V> owner, TreeNode<K, V>[] path, TreeNode<K, V> to, boolean reverse) {
this.owner = owner; this.owner = owner;
modCount = owner.modCount; modCount = owner.modCount;
this.path = TArrays.copyOf(path, owner.root.height); this.path = TArrays.copyOf(path, owner.root.height);
depth = path.length; depth = path.length;
this.to = to; this.to = to;
this.reverse = reverse;
} }
@Override @Override
@ -627,11 +583,12 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
} }
TreeNode<K, V> node = path[--depth]; TreeNode<K, V> node = path[--depth];
last = node; last = node;
if (node.right != null) { TreeNode<K, V> down = node.down(reverse);
node = node.right; if (down != null) {
node = down;
while (node != null) { while (node != null) {
path[depth++] = node; path[depth++] = node;
node = node.left; node = node.forward(reverse);
} }
} }
if (last == to) { if (last == to) {
@ -654,7 +611,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
} }
} }
private static class SubMap<K, V> extends TAbstractMap<K, V> implements TSortedMap<K, V>, TSerializable { private static class MapView<K, V> extends TAbstractMap<K, V> implements TSortedMap<K, V>, TSerializable {
private int modCount = -1; private int modCount = -1;
private int cachedSize; private int cachedSize;
private TTreeMap<K, V> owner; private TTreeMap<K, V> owner;
@ -665,9 +622,10 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
private boolean toIncluded; private boolean toIncluded;
private boolean toChecked; private boolean toChecked;
private EntrySet<K, V> entrySetCache; private EntrySet<K, V> entrySetCache;
private boolean reverse;
public SubMap(TTreeMap<K, V> owner, K from, boolean fromIncluded, boolean fromChecked, public MapView(TTreeMap<K, V> owner, K from, boolean fromIncluded, boolean fromChecked,
K to, boolean toIncluded, boolean toChecked) { K to, boolean toIncluded, boolean toChecked, boolean reverse) {
this.owner = owner; this.owner = owner;
this.from = from; this.from = from;
this.fromIncluded = fromIncluded; this.fromIncluded = fromIncluded;
@ -675,19 +633,26 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
this.to = to; this.to = to;
this.toIncluded = toIncluded; this.toIncluded = toIncluded;
this.toChecked = toChecked; this.toChecked = toChecked;
this.reverse = reverse;
} }
@Override @Override
public TSet<Entry<K, V>> entrySet() { public TSet<Entry<K, V>> entrySet() {
if (entrySetCache == null) { if (entrySetCache == null) {
entrySetCache = new EntrySet<>(owner, from, fromIncluded, fromChecked, to, toIncluded, toChecked); entrySetCache = new EntrySet<>(owner, from, fromIncluded,
fromChecked, to, toIncluded, toChecked, reverse);
} }
return entrySetCache; return entrySetCache;
} }
@Override @Override
public TComparator<? super K> comparator() { public TComparator<? super K> comparator() {
return owner.originalComparator; if (!reverse) {
return owner.originalComparator;
} else {
owner.ensureRevertedComparator();
return owner.revertedComparator;
}
} }
private void checkKey(K key) { private void checkKey(K key) {
@ -732,7 +697,8 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
modCount = owner.modCount; modCount = owner.modCount;
size = owner.size(); size = owner.size();
if (fromChecked) { if (fromChecked) {
TreeNode<K, V>[] path = fromIncluded ? owner.pathToPrev(from) : owner.pathToExactOrPrev(from); TreeNode<K, V>[] path = fromIncluded ? owner.pathToNext(from, true) :
owner.pathToExactOrNext(from, true);
for (TreeNode<K, V> node : path) { for (TreeNode<K, V> node : path) {
if (node.left != null) { if (node.left != null) {
size -= node.left.size; size -= node.left.size;
@ -741,7 +707,8 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
size -= path.length; size -= path.length;
} }
if (toChecked) { if (toChecked) {
TreeNode<K, V> path[] = toIncluded ? owner.pathToNext(to) : owner.pathToExactOrNext(to); TreeNode<K, V> path[] = toIncluded ? owner.pathToNext(to, false) :
owner.pathToExactOrNext(to, false);
for (TreeNode<K, V> node : path) { for (TreeNode<K, V> node : path) {
if (node.right != null) { if (node.right != null) {
size -= node.right.size; size -= node.right.size;
@ -777,24 +744,32 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
public TSortedMap<K, V> subMap(K fromKey, K toKey) { public TSortedMap<K, V> subMap(K fromKey, K toKey) {
checkKey(fromKey); checkKey(fromKey);
checkKey(toKey); checkKey(toKey);
return new SubMap<>(owner, fromKey, true, true, toKey, false, true); return new MapView<>(owner, fromKey, true, true, toKey, false, true, reverse);
} }
@Override @Override
public TSortedMap<K, V> headMap(K toKey) { public TSortedMap<K, V> headMap(K toKey) {
checkKey(toKey); checkKey(toKey);
return new SubMap<>(owner, from, fromIncluded, fromChecked, toKey, false, true); if (!reverse) {
return new MapView<>(owner, from, fromIncluded, fromChecked, toKey, false, true, false);
} else {
return new MapView<>(owner, toKey, false, true, to, toIncluded, toChecked, true);
}
} }
@Override @Override
public TSortedMap<K, V> tailMap(K fromKey) { public TSortedMap<K, V> tailMap(K fromKey) {
checkKey(fromKey); checkKey(fromKey);
return new SubMap<>(owner, fromKey, true, true, to, toIncluded, toChecked); if (!reverse) {
return new MapView<>(owner, fromKey, true, true, to, toIncluded, toChecked, false);
} else {
return new MapView<>(owner, from, fromIncluded, toChecked, fromKey, true, true, true);
}
} }
@Override @Override
public K firstKey() { public K firstKey() {
TreeNode<K, V> node = firstNode(); TreeNode<K, V> node = !reverse ? firstNode() : lastNode();
if (node == null) { if (node == null) {
throw new TNoSuchElementException(); throw new TNoSuchElementException();
} }
@ -803,7 +778,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
@Override @Override
public K lastKey() { public K lastKey() {
TreeNode<K, V> node = lastNode(); TreeNode<K, V> node = !reverse ? lastNode() : firstNode();
if (node == null) { if (node == null) {
throw new TNoSuchElementException(); throw new TNoSuchElementException();
} }
@ -813,9 +788,9 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
private TreeNode<K, V> firstNode() { private TreeNode<K, V> firstNode() {
TreeNode<K, V> node; TreeNode<K, V> node;
if (fromChecked) { if (fromChecked) {
node = fromIncluded ? owner.findExactOrNext(from) : owner.findNext(from); node = fromIncluded ? owner.findExactOrNext(from, false) : owner.findNext(from, false);
} else { } else {
node = owner.firstNode(); node = owner.firstNode(false);
} }
if (toChecked) { if (toChecked) {
int cmp = owner.comparator.compare(node.getKey(), to); int cmp = owner.comparator.compare(node.getKey(), to);
@ -829,9 +804,9 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
private TreeNode<K, V> lastNode() { private TreeNode<K, V> lastNode() {
TreeNode<K, V> node; TreeNode<K, V> node;
if (toChecked) { if (toChecked) {
node = toIncluded ? owner.findExactOrPrev(to) : owner.findPrev(to); node = toIncluded ? owner.findExactOrNext(to, true) : owner.findNext(to, true);
} else { } else {
node = owner.lastNode(); node = owner.firstNode(true);
} }
if (fromChecked) { if (fromChecked) {
int cmp = owner.comparator.compare(node.getKey(), from); int cmp = owner.comparator.compare(node.getKey(), from);