Fixing bugs found when implementing Bidirectional Iterator unit tests.
-Fixed: AbstractList/ImmutableList/ArraySet/ArrayMap skip/back implementation was causing crashes and didn't update the last returned value. -Fixed: ArraySet/ArrayMap previous was not subtracting before returning value. -Fixed: BidirectionalIterator back was calling the object variant instead of the TypeSpecific Variant. -Fixed: TreeSets/Maps Iterator now fully supports backwards Iterating. -Added: Specialized skip/back function to improve speed in ImmutableHashSet/LinkedHashSet/CustomLinkedHashSet
This commit is contained in:
+111
-41
@@ -2118,26 +2118,36 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
class DecsendingSubEntryIterator extends SubMapEntryIterator implements ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE>
|
||||
{
|
||||
public DecsendingSubEntryIterator(Node KEY_VALUE_GENERIC_TYPE first, Node KEY_VALUE_GENERIC_TYPE forwardFence, Node KEY_VALUE_GENERIC_TYPE backwardFence) {
|
||||
super(first, forwardFence, backwardFence);
|
||||
super(first, forwardFence, backwardFence, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node KEY_VALUE_GENERIC_TYPE moveNext(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node KEY_VALUE_GENERIC_TYPE movePrevious(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
return nextEntry();
|
||||
return previousEntry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
return previousEntry();
|
||||
return nextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
class AcsendingSubEntryIterator extends SubMapEntryIterator implements ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE>
|
||||
{
|
||||
public AcsendingSubEntryIterator(Node KEY_VALUE_GENERIC_TYPE first, Node KEY_VALUE_GENERIC_TYPE forwardFence, Node KEY_VALUE_GENERIC_TYPE backwardFence) {
|
||||
super(first, forwardFence, backwardFence);
|
||||
super(first, forwardFence, backwardFence, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2156,26 +2166,36 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
class DecsendingSubKeyIterator extends SubMapEntryIterator implements BI_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
public DecsendingSubKeyIterator(Node KEY_VALUE_GENERIC_TYPE first, Node KEY_VALUE_GENERIC_TYPE forwardFence, Node KEY_VALUE_GENERIC_TYPE backwardFence) {
|
||||
super(first, forwardFence, backwardFence);
|
||||
super(first, forwardFence, backwardFence, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node KEY_VALUE_GENERIC_TYPE moveNext(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node KEY_VALUE_GENERIC_TYPE movePrevious(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
return nextEntry().key;
|
||||
return previousEntry().key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
return previousEntry().key;
|
||||
return nextEntry().key;
|
||||
}
|
||||
}
|
||||
|
||||
class AcsendingSubKeyIterator extends SubMapEntryIterator implements BI_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
public AcsendingSubKeyIterator(Node KEY_VALUE_GENERIC_TYPE first, Node KEY_VALUE_GENERIC_TYPE forwardFence, Node KEY_VALUE_GENERIC_TYPE backwardFence) {
|
||||
super(first, forwardFence, backwardFence);
|
||||
super(first, forwardFence, backwardFence, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2194,7 +2214,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
class AcsendingSubValueIterator extends SubMapEntryIterator implements VALUE_BI_ITERATOR VALUE_GENERIC_TYPE
|
||||
{
|
||||
public AcsendingSubValueIterator(Node KEY_VALUE_GENERIC_TYPE first, Node KEY_VALUE_GENERIC_TYPE forwardFence, Node KEY_VALUE_GENERIC_TYPE backwardFence) {
|
||||
super(first, forwardFence, backwardFence);
|
||||
super(first, forwardFence, backwardFence, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2213,39 +2233,60 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
class DecsendingSubValueIterator extends SubMapEntryIterator implements VALUE_BI_ITERATOR VALUE_GENERIC_TYPE
|
||||
{
|
||||
public DecsendingSubValueIterator(Node KEY_VALUE_GENERIC_TYPE first, Node KEY_VALUE_GENERIC_TYPE forwardFence, Node KEY_VALUE_GENERIC_TYPE backwardFence) {
|
||||
super(first, forwardFence, backwardFence);
|
||||
super(first, forwardFence, backwardFence, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node KEY_VALUE_GENERIC_TYPE moveNext(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node KEY_VALUE_GENERIC_TYPE movePrevious(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE VALUE_PREVIOUS() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
return nextEntry().value;
|
||||
return previousEntry().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE VALUE_NEXT() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
return previousEntry().value;
|
||||
return nextEntry().value;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SubMapEntryIterator
|
||||
{
|
||||
final boolean isForward;
|
||||
boolean wasForward;
|
||||
Node KEY_VALUE_GENERIC_TYPE lastReturned;
|
||||
Node KEY_VALUE_GENERIC_TYPE next;
|
||||
Node KEY_VALUE_GENERIC_TYPE previous;
|
||||
boolean unboundForwardFence;
|
||||
boolean unboundBackwardFence;
|
||||
KEY_TYPE forwardFence;
|
||||
KEY_TYPE backwardFence;
|
||||
|
||||
public SubMapEntryIterator(Node KEY_VALUE_GENERIC_TYPE first, Node KEY_VALUE_GENERIC_TYPE forwardFence, Node KEY_VALUE_GENERIC_TYPE backwardFence)
|
||||
{
|
||||
public SubMapEntryIterator(Node KEY_VALUE_GENERIC_TYPE first, Node KEY_VALUE_GENERIC_TYPE forwardFence, Node KEY_VALUE_GENERIC_TYPE backwardFence, boolean isForward) {
|
||||
next = first;
|
||||
previous = first == null ? null : movePrevious(first);
|
||||
this.forwardFence = forwardFence == null ? EMPTY_KEY_VALUE : forwardFence.key;
|
||||
this.backwardFence = backwardFence == null ? EMPTY_KEY_VALUE : backwardFence.key;
|
||||
unboundForwardFence = forwardFence == null;
|
||||
unboundBackwardFence = backwardFence == null;
|
||||
this.isForward = isForward;
|
||||
}
|
||||
|
||||
protected Node KEY_VALUE_GENERIC_TYPE moveNext(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.next();
|
||||
}
|
||||
|
||||
protected Node KEY_VALUE_GENERIC_TYPE movePrevious(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.previous();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
@@ -2254,26 +2295,30 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
|
||||
protected Node KEY_VALUE_GENERIC_TYPE nextEntry() {
|
||||
lastReturned = next;
|
||||
previous = next;
|
||||
Node KEY_VALUE_GENERIC_TYPE result = next;
|
||||
next = next.next();
|
||||
wasForward = true;
|
||||
next = moveNext(next);
|
||||
wasForward = isForward;
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean hasPrevious() {
|
||||
return next != null && (unboundBackwardFence || next.key != backwardFence);
|
||||
return previous != null && (unboundBackwardFence || previous.key != backwardFence);
|
||||
}
|
||||
|
||||
protected Node KEY_VALUE_GENERIC_TYPE previousEntry() {
|
||||
lastReturned = next;
|
||||
Node KEY_VALUE_GENERIC_TYPE result = next;
|
||||
next = next.previous();
|
||||
wasForward = false;
|
||||
lastReturned = previous;
|
||||
next = previous;
|
||||
Node KEY_VALUE_GENERIC_TYPE result = previous;
|
||||
previous = movePrevious(previous);
|
||||
wasForward = !isForward;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if(lastReturned == null) throw new IllegalStateException();
|
||||
if(next == lastReturned) next = moveNext(next);
|
||||
if(previous == lastReturned) previous = movePrevious(previous);
|
||||
if(wasForward && lastReturned.needsSuccessor()) next = lastReturned;
|
||||
map.removeNode(lastReturned);
|
||||
lastReturned = null;
|
||||
@@ -2587,19 +2632,29 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
class DescendingKeyIterator extends MapEntryIterator implements BI_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
public DescendingKeyIterator(Node KEY_VALUE_GENERIC_TYPE first) {
|
||||
super(first);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
return nextEntry().key;
|
||||
super(first, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node KEY_VALUE_GENERIC_TYPE moveNext(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node KEY_VALUE_GENERIC_TYPE movePrevious(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
return previousEntry().key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
return previousEntry().key;
|
||||
return nextEntry().key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2607,7 +2662,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
{
|
||||
public AscendingMapEntryIterator(Node KEY_VALUE_GENERIC_TYPE first)
|
||||
{
|
||||
super(first);
|
||||
super(first, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2626,7 +2681,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
class AscendingValueIterator extends MapEntryIterator implements VALUE_BI_ITERATOR VALUE_GENERIC_TYPE
|
||||
{
|
||||
public AscendingValueIterator(Node KEY_VALUE_GENERIC_TYPE first) {
|
||||
super(first);
|
||||
super(first, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2645,7 +2700,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
class AscendingKeyIterator extends MapEntryIterator implements BI_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
public AscendingKeyIterator(Node KEY_VALUE_GENERIC_TYPE first) {
|
||||
super(first);
|
||||
super(first, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2663,13 +2718,24 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
|
||||
abstract class MapEntryIterator
|
||||
{
|
||||
final boolean isForward;
|
||||
boolean wasMoved = false;
|
||||
Node KEY_VALUE_GENERIC_TYPE lastReturned;
|
||||
Node KEY_VALUE_GENERIC_TYPE next;
|
||||
Node KEY_VALUE_GENERIC_TYPE previous;
|
||||
|
||||
public MapEntryIterator(Node KEY_VALUE_GENERIC_TYPE first)
|
||||
{
|
||||
public MapEntryIterator(Node KEY_VALUE_GENERIC_TYPE first, boolean isForward) {
|
||||
next = first;
|
||||
previous = first == null ? null : movePrevious(first);
|
||||
this.isForward = isForward;
|
||||
}
|
||||
|
||||
protected Node KEY_VALUE_GENERIC_TYPE moveNext(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.next();
|
||||
}
|
||||
|
||||
protected Node KEY_VALUE_GENERIC_TYPE movePrevious(Node KEY_VALUE_GENERIC_TYPE node) {
|
||||
return node.previous();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
@@ -2678,26 +2744,30 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
||||
|
||||
protected Node KEY_VALUE_GENERIC_TYPE nextEntry() {
|
||||
lastReturned = next;
|
||||
previous = next;
|
||||
Node KEY_VALUE_GENERIC_TYPE result = next;
|
||||
next = next.next();
|
||||
wasMoved = true;
|
||||
next = moveNext(next);
|
||||
wasMoved = isForward;
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean hasPrevious() {
|
||||
return next != null;
|
||||
return previous != null;
|
||||
}
|
||||
|
||||
protected Node KEY_VALUE_GENERIC_TYPE previousEntry() {
|
||||
lastReturned = next;
|
||||
Node KEY_VALUE_GENERIC_TYPE result = next;
|
||||
next = next.previous();
|
||||
wasMoved = false;
|
||||
lastReturned = previous;
|
||||
next = previous;
|
||||
Node KEY_VALUE_GENERIC_TYPE result = previous;
|
||||
previous = movePrevious(previous);
|
||||
wasMoved = !isForward;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if(lastReturned == null) throw new IllegalStateException();
|
||||
if(next == lastReturned) next = moveNext(next);
|
||||
if(previous == lastReturned) previous = movePrevious(previous);
|
||||
if(wasMoved && lastReturned.needsSuccessor()) next = lastReturned;
|
||||
removeNode(lastReturned);
|
||||
lastReturned = null;
|
||||
|
||||
Reference in New Issue
Block a user