From 3dc42b95f5533ed0b7e16a685180098fb39f256c Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Wed, 2 Apr 2014 13:47:37 +0400 Subject: [PATCH] Adds generalization of TreeMap to further enable the full support of NavigableMap --- .../teavm/classlib/java/util/TTreeMap.java | 253 ++++++++---------- 1 file changed, 114 insertions(+), 139 deletions(-) diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTreeMap.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTreeMap.java index ffd9071c1..cb591eb93 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTreeMap.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTreeMap.java @@ -78,11 +78,20 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS size += right.size; } } + + public TreeNode forward(boolean reverse) { + return !reverse ? left : right; + } + + public TreeNode down(boolean reverse) { + return !reverse ? right : left; + } } TreeNode root; private TComparator comparator; private TComparator originalComparator; + private TComparator revertedComparator; private int modCount = 0; private EntrySet cachedEntrySet; @@ -124,6 +133,16 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS fillMap(entries); } + private void ensureRevertedComparator() { + if (revertedComparator == null) { + revertedComparator = new TComparator() { + @Override public int compare(K o1, K o2) { + return -originalComparator.compare(o1, o2); + } + }; + } + } + private void fillMap(Entry[] entries) { root = createNode(entries, 0, entries.length - 1); } @@ -201,25 +220,28 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS return null; } - TreeNode findExactOrNext(Object key) { + TreeNode findExactOrNext(Object key, boolean reverse) { TreeNode node = root; - TreeNode lastLeftTurn = null; + TreeNode lastForward = null; while (node != null) { @SuppressWarnings("unchecked") int cmp = comparator.compare((K)key, node.getKey()); + if (reverse) { + cmp = -cmp; + } if (cmp == 0) { return node; } else if (cmp < 0) { - lastLeftTurn = node; - node = node.left; + lastForward = node; + node = node.forward(reverse); } else { - node = node.right; + node = node.down(reverse); } } - return lastLeftTurn; + return lastForward; } - TreeNode[] pathToExactOrNext(Object key) { + TreeNode[] pathToExactOrNext(Object key, boolean reverse) { @SuppressWarnings("unchecked") TreeNode[] path = (TreeNode[])new TreeNode[height()]; int depth = 0; @@ -227,36 +249,42 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS while (node != null) { @SuppressWarnings("unchecked") int cmp = comparator.compare((K)key, node.getKey()); + if (reverse) { + cmp = -cmp; + } if (cmp == 0) { path[depth++] = node; break; } else if (cmp < 0) { path[depth++] = node; - node = node.left; + node = node.forward(reverse); } else { - node = node.right; + node = node.down(reverse); } } return TArrays.copyOf(path, depth); } - TreeNode findNext(Object key) { + TreeNode findNext(Object key, boolean reverse) { TreeNode node = root; - TreeNode lastLeftTurn = null; + TreeNode lastForward = null; while (node != null) { @SuppressWarnings("unchecked") int cmp = comparator.compare((K)key, node.getKey()); + if (reverse) { + cmp = -cmp; + } if (cmp < 0) { - lastLeftTurn = node; - node = node.left; + lastForward = node; + node = node.forward(reverse); } else { - node = node.right; + node = node.down(reverse); } } - return lastLeftTurn; + return lastForward; } - TreeNode[] pathToNext(Object key) { + TreeNode[] pathToNext(Object key, boolean reverse) { @SuppressWarnings("unchecked") TreeNode[] path = (TreeNode[])new TreeNode[height()]; int depth = 0; @@ -264,97 +292,27 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS while (node != null) { @SuppressWarnings("unchecked") int cmp = comparator.compare((K)key, node.getKey()); + if (reverse) { + cmp = -cmp; + } if (cmp < 0) { path[depth++] = node; - node = node.left; + node = node.forward(reverse); } else { - node = node.right; + node = node.down(reverse); } } return TArrays.copyOf(path, depth); } - TreeNode findExactOrPrev(Object key) { - TreeNode node = root; - TreeNode 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[] pathToExactOrPrev(Object key) { - @SuppressWarnings("unchecked") - TreeNode[] path = (TreeNode[])new TreeNode[height()]; - int depth = 0; - TreeNode 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[] pathToFirst() { + TreeNode[] pathToFirst(boolean reverse) { @SuppressWarnings("unchecked") TreeNode[] path = (TreeNode[])new TreeNode[height()]; int depth = 0; TreeNode node = root; while (node != null) { path[depth++] = node; - node = node.left; - } - return TArrays.copyOf(path, depth); - } - - TreeNode findPrev(Object key) { - TreeNode node = root; - TreeNode 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[] pathToPrev(Object key) { - @SuppressWarnings("unchecked") - TreeNode[] path = (TreeNode[])new TreeNode[height()]; - int depth = 0; - TreeNode 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; - } + node = node.forward(reverse); } return TArrays.copyOf(path, depth); } @@ -415,7 +373,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS @Override public TSet> entrySet() { 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; } @@ -430,22 +388,22 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS if (comparator.compare(fromKey, toKey) > 0) { 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 public TSortedMap 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 public TSortedMap 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 public K firstKey() { - TreeNode node = firstNode(); + TreeNode node = firstNode(false); if (node == null) { throw new TNoSuchElementException(); } @@ -454,29 +412,19 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS @Override public K lastKey() { - TreeNode node = lastNode(); + TreeNode node = firstNode(true); if (node == null) { throw new TNoSuchElementException(); } return node.getKey(); } - private TreeNode firstNode() { + private TreeNode firstNode(boolean reverse) { TreeNode node = root; TreeNode prev = null; while (node != null) { prev = node; - node = node.left; - } - return prev; - } - - private TreeNode lastNode() { - TreeNode node = root; - TreeNode prev = null; - while (node != null) { - prev = node; - node = node.right; + node = node.forward(reverse); } return prev; } @@ -507,9 +455,10 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS private boolean toIncluded; private boolean toChecked; private int cachedSize; + private boolean reverse; public EntrySet(TTreeMap 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.from = from; this.fromIncluded = fromIncluded; @@ -517,6 +466,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS this.to = to; this.toIncluded = toIncluded; this.toChecked = toChecked; + this.reverse = reverse; } @Override @@ -526,7 +476,8 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS modCount = owner.modCount; size = owner.size(); if (fromChecked) { - TreeNode[] path = fromIncluded ? owner.pathToPrev(from) : owner.pathToExactOrPrev(from); + TreeNode[] path = fromIncluded ? owner.pathToNext(from, true) : + owner.pathToExactOrNext(from, true); for (TreeNode node : path) { if (node.left != null) { size -= node.left.size; @@ -535,7 +486,8 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS size -= path.length; } if (toChecked) { - TreeNode path[] = toIncluded ? owner.pathToNext(to) : owner.pathToExactOrNext(to); + TreeNode path[] = toIncluded ? owner.pathToNext(to, false) : + owner.pathToExactOrNext(to, false); for (TreeNode node : path) { if (node.right != null) { size -= node.right.size; @@ -551,18 +503,20 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS @Override public TIterator> iterator() { TreeNode[] fromPath; + K from = !reverse ? this.from : this.to; + K to = !reverse ? this.to : this.from; if (fromChecked) { - fromPath = fromIncluded ? owner.pathToExactOrNext(from) : owner.pathToNext(from); + fromPath = fromIncluded ? owner.pathToExactOrNext(from, reverse) : owner.pathToNext(from, reverse); } else { - fromPath = owner.pathToFirst(); + fromPath = owner.pathToFirst(reverse); } TreeNode toEntry; if (toChecked) { - toEntry = toIncluded ? owner.findExactOrPrev(to) : owner.findPrev(to); + toEntry = toIncluded ? owner.findExactOrNext(to, !reverse) : owner.findNext(to, !reverse); } else { - toEntry = owner.lastNode(); + toEntry = owner.firstNode(!reverse); } - return new EntryIterator<>(owner, fromPath, toEntry); + return new EntryIterator<>(owner, fromPath, toEntry, reverse); } @Override @@ -603,13 +557,15 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS private TreeNode last; private TreeNode to; private int depth; + private boolean reverse; - public EntryIterator(TTreeMap owner, TreeNode[] path, TreeNode to) { + public EntryIterator(TTreeMap owner, TreeNode[] path, TreeNode to, boolean reverse) { this.owner = owner; modCount = owner.modCount; this.path = TArrays.copyOf(path, owner.root.height); depth = path.length; this.to = to; + this.reverse = reverse; } @Override @@ -627,11 +583,12 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS } TreeNode node = path[--depth]; last = node; - if (node.right != null) { - node = node.right; + TreeNode down = node.down(reverse); + if (down != null) { + node = down; while (node != null) { path[depth++] = node; - node = node.left; + node = node.forward(reverse); } } if (last == to) { @@ -654,7 +611,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS } } - private static class SubMap extends TAbstractMap implements TSortedMap, TSerializable { + private static class MapView extends TAbstractMap implements TSortedMap, TSerializable { private int modCount = -1; private int cachedSize; private TTreeMap owner; @@ -665,9 +622,10 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS private boolean toIncluded; private boolean toChecked; private EntrySet entrySetCache; + private boolean reverse; - public SubMap(TTreeMap owner, K from, boolean fromIncluded, boolean fromChecked, - K to, boolean toIncluded, boolean toChecked) { + public MapView(TTreeMap owner, K from, boolean fromIncluded, boolean fromChecked, + K to, boolean toIncluded, boolean toChecked, boolean reverse) { this.owner = owner; this.from = from; this.fromIncluded = fromIncluded; @@ -675,19 +633,26 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS this.to = to; this.toIncluded = toIncluded; this.toChecked = toChecked; + this.reverse = reverse; } @Override public TSet> entrySet() { 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; } @Override public TComparator comparator() { - return owner.originalComparator; + if (!reverse) { + return owner.originalComparator; + } else { + owner.ensureRevertedComparator(); + return owner.revertedComparator; + } } private void checkKey(K key) { @@ -732,7 +697,8 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS modCount = owner.modCount; size = owner.size(); if (fromChecked) { - TreeNode[] path = fromIncluded ? owner.pathToPrev(from) : owner.pathToExactOrPrev(from); + TreeNode[] path = fromIncluded ? owner.pathToNext(from, true) : + owner.pathToExactOrNext(from, true); for (TreeNode node : path) { if (node.left != null) { size -= node.left.size; @@ -741,7 +707,8 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS size -= path.length; } if (toChecked) { - TreeNode path[] = toIncluded ? owner.pathToNext(to) : owner.pathToExactOrNext(to); + TreeNode path[] = toIncluded ? owner.pathToNext(to, false) : + owner.pathToExactOrNext(to, false); for (TreeNode node : path) { if (node.right != null) { size -= node.right.size; @@ -777,24 +744,32 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS public TSortedMap subMap(K fromKey, K toKey) { checkKey(fromKey); checkKey(toKey); - return new SubMap<>(owner, fromKey, true, true, toKey, false, true); + return new MapView<>(owner, fromKey, true, true, toKey, false, true, reverse); } @Override public TSortedMap headMap(K 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 public TSortedMap tailMap(K 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 public K firstKey() { - TreeNode node = firstNode(); + TreeNode node = !reverse ? firstNode() : lastNode(); if (node == null) { throw new TNoSuchElementException(); } @@ -803,7 +778,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS @Override public K lastKey() { - TreeNode node = lastNode(); + TreeNode node = !reverse ? lastNode() : firstNode(); if (node == null) { throw new TNoSuchElementException(); } @@ -813,9 +788,9 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS private TreeNode firstNode() { TreeNode node; if (fromChecked) { - node = fromIncluded ? owner.findExactOrNext(from) : owner.findNext(from); + node = fromIncluded ? owner.findExactOrNext(from, false) : owner.findNext(from, false); } else { - node = owner.firstNode(); + node = owner.firstNode(false); } if (toChecked) { int cmp = owner.comparator.compare(node.getKey(), to); @@ -829,9 +804,9 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS private TreeNode lastNode() { TreeNode node; if (toChecked) { - node = toIncluded ? owner.findExactOrPrev(to) : owner.findPrev(to); + node = toIncluded ? owner.findExactOrNext(to, true) : owner.findNext(to, true); } else { - node = owner.lastNode(); + node = owner.firstNode(true); } if (fromChecked) { int cmp = owner.comparator.compare(node.getKey(), from);