Skip to content

Commit 5bfc90c

Browse files
committed
Introduced jump inside iterator
This is a memory optimization for the case when a user required to modify iterator by moving it to a desire position. This works the same way as `iteraotr(fromElement)` but doesn't create a new iterator that decreases memory footprint at an algorithms which makes a lot of jumps.
1 parent 7944e1d commit 5bfc90c

File tree

5 files changed

+99
-0
lines changed

5 files changed

+99
-0
lines changed

drv/AVLTreeSet.drv

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,17 @@ public class AVL_TREE_SET KEY_GENERIC extends ABSTRACT_SORTED_SET KEY_GENERIC im
11271127
AVL_TREE_SET.this.remove(curr.key);
11281128
curr = null;
11291129
}
1130+
1131+
@Override
1132+
public void jump(final KEY_GENERIC_TYPE fromElement) {
1133+
if ((next = locateKey(fromElement)) != null) {
1134+
if (compare(next.key, fromElement) <= 0) {
1135+
prev = next;
1136+
next = next.next();
1137+
}
1138+
else prev = next.prev();
1139+
}
1140+
}
11301141
}
11311142

11321143
@Override

drv/Iterator.drv

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,27 @@ public interface KEY_ITERATOR KEY_GENERIC extends Iterator<KEY_GENERIC_CLASS> {
153153
while(i-- != 0 && hasNext()) NEXT_KEY();
154154
return n - i - 1;
155155
}
156+
157+
/** Moves back or forward to the elements in this set,
158+
* starting from a given element of the domain.
159+
*
160+
* <p>This method moves an iterator to the specified starting point.
161+
* The starting point is any element comparable to the elements of this set
162+
* (even if it does not actually belong to the set).
163+
* The next element of the returned iterator is the least element of
164+
* the set that is greater than the starting point (if there are no
165+
* elements greater than the starting point, {@link
166+
* it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
167+
* {@code false}). The previous element of the returned iterator is
168+
* the greatest element of the set that is smaller than or equal to the
169+
* starting point (if there are no elements smaller than or equal to the
170+
* starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
171+
* hasPrevious()} will return {@code false}).
172+
*
173+
* @param fromElement an element to start from.
174+
* @throws UnsupportedOperationException if this set does not support jump at iterator.
175+
*/
176+
default void jump(final KEY_GENERIC_TYPE fromElement) {
177+
throw new UnsupportedOperationException();
178+
}
156179
}

drv/RBTreeSet.drv

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,17 @@ public class RB_TREE_SET KEY_GENERIC extends ABSTRACT_SORTED_SET KEY_GENERIC imp
10551055
RB_TREE_SET.this.remove(curr.key);
10561056
curr = null;
10571057
}
1058+
1059+
@Override
1060+
public void jump(final KEY_GENERIC_TYPE fromElement) {
1061+
if ((next = locateKey(fromElement)) != null) {
1062+
if (compare(next.key, fromElement) <= 0) {
1063+
prev = next;
1064+
next = next.next();
1065+
}
1066+
else prev = next.prev();
1067+
}
1068+
}
10581069
}
10591070

10601071
@Override

test/it/unimi/dsi/fastutil/ints/IntAVLTreeSetTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,31 @@ public void testGet() {
4141
public void testLegacyMainMethodTests() throws Exception {
4242
MainRunner.callMainIfExists(IntAVLTreeSet.class, "test", /*num=*/"20", /*seed=*/"423429");
4343
}
44+
45+
@Test
46+
public void testIteratorJump() {
47+
final IntRBTreeSet s = new IntRBTreeSet();
48+
for (int i = 0; i < 100; i += 3) {
49+
s.add(i);
50+
}
51+
52+
final IntBidirectionalIterator it = s.iterator(50);
53+
54+
assertTrue(it.hasNext());
55+
assertEquals(51, it.nextInt());
56+
57+
it.jump(50);
58+
assertTrue(it.hasPrevious());
59+
assertEquals(48, it.previousInt());
60+
61+
it.jump(-1);
62+
assertTrue(it.hasNext());
63+
assertFalse(it.hasPrevious());
64+
assertEquals(0, it.nextInt());
65+
66+
it.jump(100);
67+
assertFalse(it.hasNext());
68+
assertTrue(it.hasPrevious());
69+
assertEquals(99, it.previousInt());
70+
}
4471
}

test/it/unimi/dsi/fastutil/ints/IntRBTreeSetTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,31 @@ public void testAddAndGet() {
4242
public void testLegacyMainMethodTests() throws Exception {
4343
MainRunner.callMainIfExists(IntRBTreeSet.class, "test", /*num=*/"20", /*seed=*/"423429");
4444
}
45+
46+
@Test
47+
public void testIteratorJump() {
48+
final IntRBTreeSet s = new IntRBTreeSet();
49+
for (int i = 0; i < 100; i += 3) {
50+
s.add(i);
51+
}
52+
53+
final IntBidirectionalIterator it = s.iterator(50);
54+
55+
assertTrue(it.hasNext());
56+
assertEquals(51, it.nextInt());
57+
58+
it.jump(50);
59+
assertTrue(it.hasPrevious());
60+
assertEquals(48, it.previousInt());
61+
62+
it.jump(-1);
63+
assertTrue(it.hasNext());
64+
assertFalse(it.hasPrevious());
65+
assertEquals(0, it.nextInt());
66+
67+
it.jump(100);
68+
assertFalse(it.hasNext());
69+
assertTrue(it.hasPrevious());
70+
assertEquals(99, it.previousInt());
71+
}
4572
}

0 commit comments

Comments
 (0)