mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 16:04:10 -08:00
Adds generalization of TreeMap to further enable the full support of
NavigableMap
This commit is contained in:
parent
05569f4eef
commit
3dc42b95f5
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user