Skip to content

Commit

Permalink
Introduced MovableBidirectionalIterator
Browse files Browse the repository at this point in the history
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.

So, user simple calls `move(fromElement)`.

It also introduces `begin()` which moves iterator to the first position,
and `end()` which moves iterator to the last element.
  • Loading branch information
catap committed Sep 29, 2023
1 parent 134cee3 commit 8af5777
Show file tree
Hide file tree
Showing 19 changed files with 852 additions and 79 deletions.
91 changes: 78 additions & 13 deletions drv/AVLTreeMap.drv
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package PACKAGE;

#if ! KEYS_REFERENCE
import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
import it.unimi.dsi.fastutil.objects.ObjectMovableBidirectionalIterator;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
#endif
Expand Down Expand Up @@ -1185,6 +1185,30 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL
while(i-- != 0 && hasPrevious()) previousEntry();
return n - i - 1;
}

public void moveKey(final KEY_GENERIC_TYPE fromElement) {
prev = null;
curr = prev;
if ((next = locateKey(fromElement)) != null) {
if (compare(next.key, fromElement) <= 0) {
prev = next;
next = next.next();
}
else prev = next.prev();
}
}

public void beginKey() {
next = firstEntry;
prev = next.prev();
curr = prev;
}

public void endKey() {
next = lastEntry;
prev = next.prev();
curr = prev;
}
}


Expand All @@ -1193,7 +1217,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL
* <p>This class can iterate in both directions on a threaded tree.
*/

private class EntryIterator extends TreeIterator implements ObjectListIterator<MAP.Entry KEY_VALUE_GENERIC> {
private class EntryIterator extends TreeIterator implements ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC>, ObjectListIterator<MAP.Entry KEY_VALUE_GENERIC> {
EntryIterator() {}

EntryIterator(final KEY_GENERIC_TYPE k) {
Expand All @@ -1211,6 +1235,15 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL

@Override
public void add(MAP.Entry KEY_VALUE_GENERIC ok) { throw new UnsupportedOperationException(); }

@Override
public void move(final MAP.Entry KEY_VALUE_GENERIC fromElement) { moveKey(fromElement.ENTRY_GET_KEY()); }

@Override
public void begin() { beginKey(); }

@Override
public void end() { endKey(); }
}


Expand All @@ -1227,10 +1260,10 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL
public Comparator<? super MAP.Entry KEY_VALUE_GENERIC> comparator() { return comparator; }

@Override
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> iterator() { return new EntryIterator(); }
public ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> iterator() { return new EntryIterator(); }

@Override
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> iterator(final MAP.Entry KEY_VALUE_GENERIC from) { return new EntryIterator(from.ENTRY_GET_KEY()); }
public ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> iterator(final MAP.Entry KEY_VALUE_GENERIC from) { return new EntryIterator(from.ENTRY_GET_KEY()); }

@Override
SUPPRESS_WARNINGS_KEY_UNCHECKED
Expand Down Expand Up @@ -1297,21 +1330,27 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL
* simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
* their type-specific counterparts) so that they return keys instead of entries.
*/
private final class KeyIterator extends TreeIterator implements KEY_LIST_ITERATOR KEY_GENERIC {
private final class KeyIterator extends TreeIterator implements KEY_MOVE_BIDI_ITERATOR KEY_GENERIC, KEY_LIST_ITERATOR KEY_GENERIC {
public KeyIterator() {}
public KeyIterator(final KEY_GENERIC_TYPE k) { super(k); }
@Override
public KEY_GENERIC_TYPE NEXT_KEY() { return nextEntry().key; }
@Override
public KEY_GENERIC_TYPE PREV_KEY() { return previousEntry().key; }
@Override
public void move(final KEY_GENERIC_TYPE fromElement) { moveKey(fromElement); }
@Override
public void begin() { beginKey(); }
@Override
public void end() { endKey(); }
}

/** A keyset implementation using a more direct implementation for iterators. */
private class KeySet extends ABSTRACT_SORTED_MAP KEY_VALUE_GENERIC.KeySet {
@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator() { return new KeyIterator(); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator() { return new KeyIterator(); }
@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new KeyIterator(from); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new KeyIterator(from); }
}

/** Returns a type-specific sorted set view of the keys contained in this map.
Expand Down Expand Up @@ -1443,9 +1482,9 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL
public ObjectSortedSet<MAP.Entry KEY_VALUE_GENERIC> ENTRYSET() {
if (entries == null) entries = new AbstractObjectSortedSet<MAP.Entry KEY_VALUE_GENERIC>() {
@Override
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> iterator() { return new SubmapEntryIterator(); }
public ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> iterator() { return new SubmapEntryIterator(); }
@Override
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> iterator(final MAP.Entry KEY_VALUE_GENERIC from) { return new SubmapEntryIterator(from.ENTRY_GET_KEY()); }
public ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> iterator(final MAP.Entry KEY_VALUE_GENERIC from) { return new SubmapEntryIterator(from.ENTRY_GET_KEY()); }
@Override
public Comparator<? super MAP.Entry KEY_VALUE_GENERIC> comparator() { return AVL_TREE_MAP.this.ENTRYSET().comparator(); }
@Override
Expand Down Expand Up @@ -1504,9 +1543,9 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL

private class KeySet extends ABSTRACT_SORTED_MAP KEY_VALUE_GENERIC.KeySet {
@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator() { return new SubmapKeyIterator(); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator() { return new SubmapKeyIterator(); }
@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new SubmapKeyIterator(from); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new SubmapKeyIterator(from); }
}

@Override
Expand Down Expand Up @@ -1706,16 +1745,36 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL
next = next.next();
if (! top && next != null && AVL_TREE_MAP.this.compare(next.key, to) >= 0) next = null;
}

@Override
public void beginKey() {
next = firstEntry();
prev = next.prev();
curr = prev;
}

@Override
public void endKey() {
next = lastEntry();
prev = next.prev();
curr = prev;
}
}

private class SubmapEntryIterator extends SubmapIterator implements ObjectListIterator<MAP.Entry KEY_VALUE_GENERIC> {
private class SubmapEntryIterator extends SubmapIterator implements ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC>, ObjectListIterator<MAP.Entry KEY_VALUE_GENERIC> {
SubmapEntryIterator() {}
SubmapEntryIterator(final KEY_GENERIC_TYPE k) { super(k); }

@Override
public MAP.Entry KEY_VALUE_GENERIC next() { return nextEntry(); }
@Override
public MAP.Entry KEY_VALUE_GENERIC previous() { return previousEntry(); }
@Override
public void move(final MAP.Entry KEY_VALUE_GENERIC from) { moveKey(from.ENTRY_GET_KEY()); }
@Override
public void begin() { beginKey(); }
@Override
public void end() { endKey(); }
}


Expand All @@ -1727,14 +1786,20 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC extends ABSTRACT_SORTED_MAP KEY_VAL
* type-specific counterparts) so that they return keys instead of
* entries.
*/
private final class SubmapKeyIterator extends SubmapIterator implements KEY_LIST_ITERATOR KEY_GENERIC {
private final class SubmapKeyIterator extends SubmapIterator implements KEY_MOVE_BIDI_ITERATOR KEY_GENERIC, KEY_LIST_ITERATOR KEY_GENERIC {
public SubmapKeyIterator() { super(); }
public SubmapKeyIterator(KEY_GENERIC_TYPE from) { super(from); }

@Override
public KEY_GENERIC_TYPE NEXT_KEY() { return nextEntry().key; }
@Override
public KEY_GENERIC_TYPE PREV_KEY() { return previousEntry().key; }
@Override
public void move(final KEY_GENERIC_TYPE from) { moveKey(from); }
@Override
public void begin() { beginKey(); }
@Override
public void end() { endKey(); }
};

/** An iterator on a subrange of values.
Expand Down
72 changes: 67 additions & 5 deletions drv/AVLTreeSet.drv
Original file line number Diff line number Diff line change
Expand Up @@ -1055,7 +1055,7 @@ public class AVL_TREE_SET KEY_GENERIC extends ABSTRACT_SORTED_SET KEY_GENERIC im
* <p>This class can iterate in both directions on a threaded tree.
*/

private class SetIterator implements KEY_LIST_ITERATOR KEY_GENERIC {
private class SetIterator implements KEY_MOVE_BIDI_ITERATOR KEY_GENERIC, KEY_LIST_ITERATOR KEY_GENERIC {
/** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or {@code null} if no previous entry exists). */
Entry KEY_GENERIC prev;
/** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or {@code null} if no next entry exists). */
Expand Down Expand Up @@ -1127,13 +1127,40 @@ public class AVL_TREE_SET KEY_GENERIC extends ABSTRACT_SORTED_SET KEY_GENERIC im
AVL_TREE_SET.this.remove(curr.key);
curr = null;
}

@Override
public void move(final KEY_GENERIC_TYPE fromElement) {
prev = null;
curr = prev;
if ((next = locateKey(fromElement)) != null) {
if (compare(next.key, fromElement) <= 0) {
prev = next;
next = next.next();
}
else prev = next.prev();
}
}

@Override
public void begin() {
prev = null;
next = firstEntry;
curr = null;
}

@Override
public void end() {
next = lastEntry;
prev = next.prev();
curr = prev;
}
}

@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator() { return new SetIterator(); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator() { return new SetIterator(); }

@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new SetIterator(from); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new SetIterator(from); }

@Override
public KEY_COMPARATOR KEY_SUPER_GENERIC comparator() { return actualComparator; }
Expand Down Expand Up @@ -1241,10 +1268,10 @@ public class AVL_TREE_SET KEY_GENERIC extends ABSTRACT_SORTED_SET KEY_GENERIC im
public KEY_COMPARATOR KEY_SUPER_GENERIC comparator() { return actualComparator; }

@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator() { return new SubsetIterator(); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator() { return new SubsetIterator(); }

@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new SubsetIterator(from); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new SubsetIterator(from); }

@Override
public SORTED_SET KEY_GENERIC headSet(final KEY_GENERIC_TYPE to) {
Expand Down Expand Up @@ -1360,6 +1387,41 @@ public class AVL_TREE_SET KEY_GENERIC extends ABSTRACT_SORTED_SET KEY_GENERIC im
next = next.next();
if (! top && next != null && AVL_TREE_SET.this.compare(next.key, to) >= 0) next = null;
}

@Override
public void move(final KEY_GENERIC_TYPE fromElement) {
prev = null;
curr = prev;
next = firstEntry();

if (next != null) {
if (! bottom && compare(fromElement, next.key) < 0) prev = null;
else if (! top && compare(fromElement, (prev = lastEntry()).key) >= 0) next = null;
else {
next = locateKey(fromElement);

if (compare(next.key, fromElement) <= 0) {
prev = next;
next = next.next();
}
else prev = next.prev();
}
}
}

@Override
public void begin() {
prev = null;
next = firstEntry();
curr = null;
}

@Override
public void end() {
next = lastEntry();
prev = next.prev();
curr = prev;
}
}
}

Expand Down
25 changes: 17 additions & 8 deletions drv/AbstractSortedMap.drv
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import VALUE_PACKAGE.VALUE_ITERATOR;
#if KEYS_REFERENCE
import java.util.Comparator;
#else
import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
import it.unimi.dsi.fastutil.objects.ObjectMovableBidirectionalIterator;
#endif

/** An abstract class providing basic methods for sorted maps implementing a type-specific interface. */
Expand Down Expand Up @@ -84,10 +84,10 @@ public abstract class ABSTRACT_SORTED_MAP KEY_VALUE_GENERIC extends ABSTRACT_MAP
public SORTED_SET KEY_GENERIC subSet(final KEY_GENERIC_TYPE from, final KEY_GENERIC_TYPE to) { return subMap(from, to).keySet(); }

@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new KeySetIterator KEY_VALUE_GENERIC_DIAMOND(ENTRYSET().iterator(new BasicEntry KEY_VALUE_GENERIC_DIAMOND(from, VALUE_NULL))); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator(final KEY_GENERIC_TYPE from) { return new KeySetIterator KEY_VALUE_GENERIC_DIAMOND(ENTRYSET().iterator(new BasicEntry KEY_VALUE_GENERIC_DIAMOND(from, VALUE_NULL))); }

@Override
public KEY_BIDI_ITERATOR KEY_GENERIC iterator() { return new KeySetIterator KEY_VALUE_GENERIC_DIAMOND(SORTED_MAPS.fastIterator(ABSTRACT_SORTED_MAP.this)); }
public KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator() { return new KeySetIterator KEY_VALUE_GENERIC_DIAMOND(SORTED_MAPS.fastIterator(ABSTRACT_SORTED_MAP.this)); }
}

/** A wrapper exhibiting a map iterator as an iterator on keys.
Expand All @@ -96,10 +96,10 @@ public abstract class ABSTRACT_SORTED_MAP KEY_VALUE_GENERIC extends ABSTRACT_MAP
* class using the corresponding iterator on entries.
*/

protected static class KeySetIterator KEY_VALUE_GENERIC implements KEY_BIDI_ITERATOR KEY_GENERIC {
protected final ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> i;
protected static class KeySetIterator KEY_VALUE_GENERIC implements KEY_MOVE_BIDI_ITERATOR KEY_GENERIC {
protected final ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> i;

public KeySetIterator(ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> i) {
public KeySetIterator(ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> i) {
this.i = i;
}

Expand All @@ -114,6 +114,15 @@ public abstract class ABSTRACT_SORTED_MAP KEY_VALUE_GENERIC extends ABSTRACT_MAP

@Override
public boolean hasPrevious() { return i.hasPrevious(); }

@Override
public void move(final KEY_GENERIC_TYPE fromElement) { i.move(new BasicEntry KEY_VALUE_GENERIC_DIAMOND(fromElement, VALUE_NULL)); }

@Override
public void begin() { i.begin(); }

@Override
public void end() { i.end(); }
}

/** {@inheritDoc}
Expand Down Expand Up @@ -154,9 +163,9 @@ public abstract class ABSTRACT_SORTED_MAP KEY_VALUE_GENERIC extends ABSTRACT_MAP
*/

protected static class ValuesIterator KEY_VALUE_GENERIC implements VALUE_ITERATOR VALUE_GENERIC {
protected final ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> i;
protected final ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> i;

public ValuesIterator(ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> i) {
public ValuesIterator(ObjectMovableBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC> i) {
this.i = i;
}

Expand Down
5 changes: 4 additions & 1 deletion drv/AbstractSortedSet.drv
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@ public abstract class ABSTRACT_SORTED_SET KEY_GENERIC extends ABSTRACT_SET KEY_G
protected ABSTRACT_SORTED_SET() {}

@Override
public abstract KEY_BIDI_ITERATOR KEY_GENERIC iterator();
public abstract KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator(KEY_GENERIC_TYPE fromElement);

@Override
public abstract KEY_MOVE_BIDI_ITERATOR KEY_GENERIC iterator();
}
Loading

0 comments on commit 8af5777

Please sign in to comment.