diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TTreeMap.java b/classlib/src/main/java/org/teavm/classlib/java/util/TTreeMap.java index 5c9da29a0..f23275f1f 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TTreeMap.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TTreeMap.java @@ -27,7 +27,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS int height = 1; int size = 1; - public TreeNode(K key) { + TreeNode(K key) { super(key, null); } @@ -548,7 +548,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS return copy; } - private static class EntrySet extends TAbstractSet> { + static class EntrySet extends TAbstractSet> { private int modCount = -1; private TTreeMap owner; private K from; @@ -560,7 +560,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS private int cachedSize; private boolean reverse; - public EntrySet(TTreeMap owner, K from, boolean fromIncluded, boolean fromChecked, + EntrySet(TTreeMap owner, K from, boolean fromIncluded, boolean fromChecked, K to, boolean toIncluded, boolean toChecked, boolean reverse) { this.owner = owner; this.from = from; @@ -615,13 +615,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS } else { fromPath = owner.pathToFirst(false); } - TreeNode toEntry; - if (toChecked) { - toEntry = toIncluded ? owner.findExactOrNext(to, true) : owner.findNext(to, true); - } else { - toEntry = owner.firstNode(true); - } - return new EntryIterator<>(owner, fromPath, toEntry, false); + return new EntryIterator<>(owner, fromPath, to, toChecked, toIncluded, false); } private TIterator> descendingIterator() { @@ -631,13 +625,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS } else { toPath = owner.pathToFirst(true); } - TreeNode fromEntry; - if (fromChecked) { - fromEntry = fromIncluded ? owner.findExactOrNext(to, false) : owner.findNext(to, false); - } else { - fromEntry = owner.firstNode(false); - } - return new EntryIterator<>(owner, toPath, fromEntry, true); + return new EntryIterator<>(owner, toPath, from, fromIncluded, fromChecked, true); } @Override @@ -671,22 +659,28 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS } } - private static class EntryIterator implements TIterator> { + static class EntryIterator implements TIterator> { private int modCount; private TTreeMap owner; private TreeNode[] path; private TreeNode last; - private TreeNode to; + private K to; + private boolean toChecked; + private boolean toIncluded; private int depth; private boolean reverse; - public EntryIterator(TTreeMap owner, TreeNode[] path, TreeNode to, boolean reverse) { + EntryIterator(TTreeMap owner, TreeNode[] path, K to, boolean toChecked, boolean toIncluded, + boolean reverse) { this.owner = owner; modCount = owner.modCount; this.path = TArrays.copyOf(path, owner.root == null ? 0 : owner.root.height); depth = path.length; this.to = to; + this.toChecked = toChecked; + this.toIncluded = toIncluded; this.reverse = reverse; + checkFinished(); } @Override @@ -712,12 +706,30 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS node = node.forward(reverse); } } - if (last == to) { - depth = 0; - } + + checkFinished(); return last; } + private void checkFinished() { + if (!toChecked || depth == 0) { + return; + } + int cmp = owner.comparator.compare(path[depth - 1].getKey(), to); + if (reverse) { + cmp = -cmp; + } + if (toIncluded) { + if (cmp > 0) { + depth = 0; + } + } else { + if (cmp >= 0) { + depth = 0; + } + } + } + @Override public void remove() { if (modCount != owner.modCount) { @@ -732,7 +744,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS } } - private static class MapView extends TAbstractMap implements TNavigableMap, TSerializable { + static class MapView extends TAbstractMap implements TNavigableMap, TSerializable { private int modCount = -1; private int cachedSize; private TTreeMap owner; @@ -746,7 +758,7 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS private boolean reverse; private NavigableKeySet cachedNavigableKeySet; - public MapView(TTreeMap owner, K from, boolean fromIncluded, boolean fromChecked, + MapView(TTreeMap owner, K from, boolean fromIncluded, boolean fromChecked, K to, boolean toIncluded, boolean toChecked, boolean reverse) { this.owner = owner; this.from = from; @@ -1079,10 +1091,10 @@ public class TTreeMap extends TAbstractMap implements TCloneable, TS } } - private static class NavigableKeySet extends TAbstractSet implements TNavigableSet { + static class NavigableKeySet extends TAbstractSet implements TNavigableSet { private TNavigableMap map; - public NavigableKeySet(TNavigableMap map) { + NavigableKeySet(TNavigableMap map) { this.map = map; } diff --git a/tests/src/test/java/org/teavm/classlib/java/util/TreeMapTest.java b/tests/src/test/java/org/teavm/classlib/java/util/TreeMapTest.java index c01d6da10..002e8faf2 100644 --- a/tests/src/test/java/org/teavm/classlib/java/util/TreeMapTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/util/TreeMapTest.java @@ -694,4 +694,20 @@ public class TreeMapTest { assertEquals(101, tm.size()); } } + + @Test + public void submap() { + TreeMap map = new TreeMap<>(); + map.put(1, 1); + map.put(3, 15); + map.put(4, 20); + map.put(6, 13); + map.put(10, 119); + + assertEquals("{}", map.subMap(0, 0).toString()); + assertEquals("{}", map.subMap(7, 9).toString()); + assertEquals("{3=15, 4=20, 6=13}", map.subMap(3, 9).toString()); + assertEquals("{10=119}", map.subMap(10, 29).toString()); + assertEquals("{}", map.subMap(29, 100).toString()); + } }