Finished the Basic Unit test frame work to ensure stablity.

-Added: 150k Unit tests.
-Fixed: Reworked the NavigableSet/Map implementations of RBTree/AVLTree/Array Sets/Maps
This commit is contained in:
Speiger 2021-12-13 10:41:20 +01:00
parent 865966db55
commit caf2f22e9f
13 changed files with 4790 additions and 4452 deletions

View File

@ -1,5 +1,9 @@
# Changelog of versions # Changelog of versions
### Version 0.5.1
- Fixed: Reworked the NavigableSet/Map implementations of RBTree/AVLTree/Array Sets/Maps so they are now deemed stable.
- Added: Another 150k Unit tests.
### Version 0.5.0 ### Version 0.5.0
- Added: 2 Helper functions to find out how many bits are required to store a Number. - Added: 2 Helper functions to find out how many bits are required to store a Number.
- Added: pour function directly into Iterable which allows to collect all elements in the Iterable directly. - Added: pour function directly into Iterable which allows to collect all elements in the Iterable directly.

View File

@ -46,7 +46,6 @@ dependencies {
runtimeOnly 'de.speiger:Simple-Code-Generator:1.0.5' runtimeOnly 'de.speiger:Simple-Code-Generator:1.0.5'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'com.google.guava:guava-testlib:31.0.1-jre' testImplementation 'com.google.guava:guava-testlib:31.0.1-jre'
} }
task generateSource(type: JavaExec) { task generateSource(type: JavaExec) {

View File

@ -207,13 +207,13 @@ public interface NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE extends SORTED_MAP KEY_VAL
default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey) { return tailMap(OBJ_TO_KEY(fromKey), true); } default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey) { return tailMap(OBJ_TO_KEY(fromKey), true); }
#else #else
@Override @Override
default MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(CLASS_TYPE key) { return lowerEntry(OBJ_TO_KEY(key)); } MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(CLASS_TYPE key);
@Override @Override
default MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(CLASS_TYPE key) { return floorEntry(OBJ_TO_KEY(key)); } MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(CLASS_TYPE key);
@Override @Override
default MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(CLASS_TYPE key) { return ceilingEntry(OBJ_TO_KEY(key)); } MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(CLASS_TYPE key);
@Override @Override
default MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(CLASS_TYPE key) { return higherEntry(OBJ_TO_KEY(key)); } MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(CLASS_TYPE key);
@Override @Override
public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, boolean fromInclusive, CLASS_TYPE toKey, boolean toInclusive); public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, boolean fromInclusive, CLASS_TYPE toKey, boolean toInclusive);

View File

@ -1,6 +1,7 @@
package speiger.src.collections.PACKAGE.sets; package speiger.src.collections.PACKAGE.sets;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
#if TYPE_OBJECT #if TYPE_OBJECT
import java.util.Comparator; import java.util.Comparator;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -19,7 +20,6 @@ import speiger.src.collections.PACKAGE.functions.function.PREDICATE;
import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR; import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR;
import speiger.src.collections.PACKAGE.collections.COLLECTION; import speiger.src.collections.PACKAGE.collections.COLLECTION;
import speiger.src.collections.PACKAGE.collections.ITERATOR; import speiger.src.collections.PACKAGE.collections.ITERATOR;
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
#if !TYPE_OBJECT #if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.utils.ITERATORS; import speiger.src.collections.PACKAGE.utils.ITERATORS;
#endif #endif
@ -557,7 +557,11 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
@Override @Override
public KEY_TYPE POLL_FIRST_KEY() { public KEY_TYPE POLL_FIRST_KEY() {
if(tree == null) throw new NoSuchElementException(); #if TYPE_OBJECT
if(tree == null) return null;
#else
if(tree == null) return getDefaultMinValue();
#endif
KEY_TYPE value = first.key; KEY_TYPE value = first.key;
removeNode(first); removeNode(first);
return value; return value;
@ -565,7 +569,11 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
@Override @Override
public KEY_TYPE POLL_LAST_KEY() { public KEY_TYPE POLL_LAST_KEY() {
if(tree == null) throw new NoSuchElementException(); #if TYPE_OBJECT
if(tree == null) return null;
#else
if(tree == null) return getDefaultMaxValue();
#endif
KEY_TYPE value = last.key; KEY_TYPE value = last.key;
removeNode(last); removeNode(last);
return value; return value;
@ -601,16 +609,16 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; } public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return new SetIterator(false); } public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return new AscendingSetIterator(first); }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) { public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
Entry KEY_GENERIC_TYPE entry = findNode(fromElement); Entry KEY_GENERIC_TYPE entry = findNode(fromElement);
return entry == null ? null : new SetIterator(entry); return entry == null ? null : new AscendingSetIterator(entry);
} }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return new SetIterator(true); } public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return new DescendingSetIterator(last); }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) {
@ -743,158 +751,174 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
} }
} }
private static class AscendingSubSet KEY_GENERIC_TYPE extends SubSet KEY_GENERIC_TYPE static class AscendingSubSet KEY_GENERIC_TYPE extends SubSet KEY_GENERIC_TYPE
{ {
AscendingSubSet(AVL_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE start, boolean loInclusive, boolean toEnd, KEY_TYPE end, boolean hiInclusive) { public AscendingSubSet(AVL_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE lo, boolean loInclusive, boolean toEnd, KEY_TYPE hi, boolean hiInclusive)
super(set, fromStart, start, loInclusive, toEnd, end, hiInclusive); {
super(set, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) { public COMPARATOR KEY_GENERIC_TYPE comparator() { return set.comparator(); }
if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement is not in Range");
if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement is not in Range"); @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive)
{
if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement out of range");
if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement out of range");
return new AscendingSubSetBRACES(set, false, fromElement, fromInclusive, false, toElement, toInclusive); return new AscendingSubSetBRACES(set, false, fromElement, fromInclusive, false, toElement, toInclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive)
if(!inRange(toElement, inclusive)) throw new IllegalArgumentException("toElement is not in Range"); {
return new AscendingSubSetBRACES(set, fromStart, start, loInclusive, false, toElement, inclusive); if(!inRange(toElement, inclusive)) throw new IllegalArgumentException("toElement out of range");
return new AscendingSubSetBRACES(set, fromStart, lo, loInclusive, false, toElement, inclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive)
if(!inRange(fromElement, inclusive)) throw new IllegalArgumentException("fromElement is not in Range"); {
return new AscendingSubSetBRACES(set, false, fromElement, inclusive, toEnd, end, hiInclusive); if(!inRange(fromElement, inclusive)) throw new IllegalArgumentException("fromElement out of range");
return new AscendingSubSetBRACES(set, false, fromElement, inclusive, toEnd, hi, hiInclusive);
} }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return new SubSetIterator(findLowest()); } public BI_ITERATOR KEY_GENERIC_TYPE iterator()
{
@Override return new AscendingSubSetIterator(absLowest(), absHighFence(), absLowFence());
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
Entry KEY_GENERIC_TYPE entry = set.findNode(fromElement);
return entry == null || !inClosedRange(fromElement) ? null : new SubSetIterator(entry);
} }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return new SubSetIterator(findHighest()); } public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement)
{
return new AscendingSubSetIterator(absLower(fromElement), absHighFence(), absLowFence());
}
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() { public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator()
return new DescendingSubSetBRACES(set, fromStart, start, loInclusive, toEnd, end, hiInclusive); {
} return new DescendingSubSetIterator(absHighest(), absLowFence(), absHighFence());
} }
private static class DescendingSubSet KEY_GENERIC_TYPE extends SubSet KEY_GENERIC_TYPE @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet()
{
if(inverse == null) inverse = new DescendingSubSetBRACES(set, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
return inverse;
}
@Override
protected Entry KEY_GENERIC_TYPE subLowest() { return absLowest(); }
@Override
protected Entry KEY_GENERIC_TYPE subHighest() { return absHighest(); }
@Override
protected Entry KEY_GENERIC_TYPE subCeiling(KEY_TYPE key) { return absCeiling(key); }
@Override
protected Entry KEY_GENERIC_TYPE subHigher(KEY_TYPE key) { return absHigher(key); }
@Override
protected Entry KEY_GENERIC_TYPE subFloor(KEY_TYPE key) { return absFloor(key); }
@Override
protected Entry KEY_GENERIC_TYPE subLower(KEY_TYPE key) { return absLower(key); }
@Override
protected Entry KEY_GENERIC_TYPE start() { return absLowest(); }
@Override
protected Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry) { return entry.next(); }
}
static class DescendingSubSet KEY_GENERIC_TYPE extends SubSet KEY_GENERIC_TYPE
{ {
COMPARATOR KEY_GENERIC_TYPE comparator; COMPARATOR KEY_GENERIC_TYPE comparator;
DescendingSubSet(AVL_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE start, boolean loInclusive, boolean toEnd, KEY_TYPE end, boolean hiInclusive) {
super(set, fromStart, start, loInclusive, toEnd, end, hiInclusive); public DescendingSubSet(AVL_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE lo, boolean loInclusive, boolean toEnd, KEY_TYPE hi, boolean hiInclusive)
comparator = set.comparator(); {
if(comparator != null) comparator = comparator.reversed(); super(set, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
#if TYPE_OBJECT
comparator = Collections.reverseOrder(set.comparator());
#else
comparator = set.comparator() == null ? COMPARATOR.of(Collections.reverseOrder()) : set.comparator().reversed();
#endif
} }
@Override @Override
public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; } public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; }
public KEY_TYPE getDefaultMaxValue() { return super.getDefaultMinValue(); }
public KEY_TYPE getDefaultMinValue() { return super.getDefaultMaxValue(); }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) {
if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement is not in Range"); if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement out of range");
if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement is not in Range"); if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement out of range");
return new DescendingSubSetBRACES(set, false, toElement, toInclusive, false, fromElement, fromInclusive); return new DescendingSubSetBRACES(set, false, fromElement, fromInclusive, false, toElement, toInclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive)
if(!inRange(toElement, inclusive)) throw new IllegalArgumentException("toElement is not in Range"); {
return new DescendingSubSetBRACES(set, false, toElement, inclusive, toEnd, end, hiInclusive); if(!inRange(toElement, inclusive)) throw new IllegalArgumentException("toElement out of range");
return new DescendingSubSetBRACES(set, false, toElement, inclusive, toEnd, hi, hiInclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) {
if(!inRange(fromElement, inclusive)) throw new IllegalArgumentException("fromElement is not in Range"); if(!inRange(fromElement, inclusive)) throw new IllegalArgumentException("fromElement out of range");
return new DescendingSubSetBRACES(set, fromStart, start, loInclusive, false, fromElement, inclusive); return new DescendingSubSetBRACES(set, fromStart, lo, loInclusive, false, fromElement, inclusive);
}
protected Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry) { return entry.previous(); }
protected Entry KEY_GENERIC_TYPE start() { return findHighest(); }
@Override
public KEY_TYPE FIRST_KEY() { return super.LAST_KEY(); }
@Override
public KEY_TYPE POLL_FIRST_KEY() { return super.POLL_LAST_KEY(); }
@Override
public KEY_TYPE LAST_KEY() { return super.FIRST_KEY(); }
@Override
public KEY_TYPE POLL_LAST_KEY() { return super.POLL_FIRST_KEY(); }
@Override
public KEY_TYPE lower(KEY_TYPE e) { return super.higher(e); }
@Override
public KEY_TYPE floor(KEY_TYPE e) { return super.ceiling(e); }
@Override
public KEY_TYPE ceiling(KEY_TYPE e) { return super.floor(e); }
@Override
public KEY_TYPE higher(KEY_TYPE e) { return super.lower(e); }
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return new DescendingSubIterator(findHighest()); }
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
Entry KEY_GENERIC_TYPE entry = set.findNode(fromElement);
return entry == null || !inClosedRange(fromElement) ? null : new DescendingSubIterator(entry);
} }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return new DescendingSubIterator(findLowest()); } public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
return new DescendingSubSetIterator(absHighest(), absLowFence(), absHighFence());
}
@Override
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() {
return new AscendingSubSetIterator(absLowest(), absHighFence(), absLowFence());
}
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() { public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() {
return new AscendingSubSetBRACES(set, fromStart, start, loInclusive, toEnd, end, hiInclusive); if(inverse == null) inverse = new AscendingSubSetBRACES(set, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
} return inverse;
private class DescendingSubIterator extends SubSetIterator
{
public DescendingSubIterator(Entry KEY_GENERIC_TYPE entry) {
super(entry);
} }
@Override @Override
protected void updateNext() { public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
next = current.previous(); return new DescendingSubSetIterator(absHigher(fromElement), absLowFence(), absHighFence());
if(!toEnd && next != null && bottomReached(next)) next = null;
} }
@Override @Override
protected void updatePrevious() { protected Entry KEY_GENERIC_TYPE subLowest() { return absHighest(); }
previous = current.next(); @Override
if(!fromStart && previous != null && topReached(previous)) previous = null; protected Entry KEY_GENERIC_TYPE subHighest() { return absLowest(); }
} @Override
} protected Entry KEY_GENERIC_TYPE subCeiling(KEY_TYPE key) { return absFloor(key); }
@Override
protected Entry KEY_GENERIC_TYPE subHigher(KEY_TYPE key) { return absLower(key); }
@Override
protected Entry KEY_GENERIC_TYPE subFloor(KEY_TYPE key) { return absCeiling(key); }
@Override
protected Entry KEY_GENERIC_TYPE subLower(KEY_TYPE key) { return absHigher(key); }
@Override
protected Entry KEY_GENERIC_TYPE start() { return absHighest(); }
@Override
protected Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry) { return entry.previous(); }
} }
private static abstract class SubSet KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE static abstract class SubSet KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE
{ {
AVL_TREE_SET KEY_GENERIC_TYPE set; final AVL_TREE_SET KEY_GENERIC_TYPE set;
KEY_TYPE start; final KEY_TYPE lo, hi;
KEY_TYPE end; final boolean fromStart, toEnd;
boolean fromStart; final boolean loInclusive, hiInclusive;
boolean toEnd; NAVIGABLE_SET KEY_GENERIC_TYPE inverse;
boolean loInclusive;
boolean hiInclusive;
SubSet(AVL_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE start, boolean loInclusive, boolean toEnd, KEY_TYPE end, boolean hiInclusive) { public SubSet(AVL_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE lo, boolean loInclusive, boolean toEnd, KEY_TYPE hi, boolean hiInclusive)
{
this.set = set; this.set = set;
this.start = start; this.lo = lo;
this.end = end; this.hi = hi;
this.fromStart = fromStart; this.fromStart = fromStart;
this.toEnd = toEnd; this.toEnd = toEnd;
this.loInclusive = loInclusive; this.loInclusive = loInclusive;
@ -903,13 +927,13 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
#if !TYPE_OBJECT #if !TYPE_OBJECT
@Override @Override
public void setDefaultMaxValue(KEY_TYPE value) { throw new UnsupportedOperationException(); } public void setDefaultMaxValue(KEY_TYPE value) { set.setDefaultMaxValue(value); }
@Override @Override
public KEY_TYPE getDefaultMaxValue() { return set.getDefaultMaxValue(); } public KEY_TYPE getDefaultMaxValue() { return set.getDefaultMaxValue(); }
@Override @Override
public void setDefaultMinValue(KEY_TYPE value) { throw new UnsupportedOperationException(); } public void setDefaultMinValue(KEY_TYPE value) { set.setDefaultMinValue(value); }
@Override @Override
public KEY_TYPE getDefaultMinValue() { return set.getDefaultMinValue(); } public KEY_TYPE getDefaultMinValue() { return set.getDefaultMinValue(); }
@ -920,80 +944,75 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
public KEY_TYPE getDefaultMinValue() { return null; } public KEY_TYPE getDefaultMinValue() { return null; }
#endif #endif
boolean tooLow(KEY_TYPE key) { return !fromStart && (loInclusive ? set.compare(key, start) < 0 : set.compare(key, start) <= 0); }
boolean tooHigh(KEY_TYPE key) { return !toEnd && (hiInclusive ? set.compare(key, end) > 0 : set.compare(key, end) >= 0); } boolean tooLow(KEY_TYPE key) {
if (!fromStart) {
int c = set.compare(key, lo);
if (c < 0 || (c == 0 && !loInclusive)) return true;
}
return false;
}
boolean tooHigh(KEY_TYPE key) {
if (!toEnd) {
int c = set.compare(key, hi);
if (c > 0 || (c == 0 && !hiInclusive)) return true;
}
return false;
}
boolean inRange(KEY_TYPE key) { return !tooLow(key) && !tooHigh(key); } boolean inRange(KEY_TYPE key) { return !tooLow(key) && !tooHigh(key); }
boolean inClosedRange(KEY_TYPE key) { return (fromStart || set.compare(key, start) >= 0) && (toEnd || set.compare(end, key) >= 0); } boolean inClosedRange(KEY_TYPE key) { return (fromStart || set.compare(key, lo) >= 0) && (toEnd || set.compare(hi, key) >= 0); }
boolean inRange(KEY_TYPE key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); } boolean inRange(KEY_TYPE key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); }
protected Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry) { return entry.next(); }
protected Entry KEY_GENERIC_TYPE start() { return findLowest(); }
@Override protected abstract Entry KEY_GENERIC_TYPE subLowest();
public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); } protected abstract Entry KEY_GENERIC_TYPE subHighest();
protected abstract Entry KEY_GENERIC_TYPE subCeiling(KEY_TYPE key);
protected abstract Entry KEY_GENERIC_TYPE subHigher(KEY_TYPE key);
protected abstract Entry KEY_GENERIC_TYPE subFloor(KEY_TYPE key);
protected abstract Entry KEY_GENERIC_TYPE subLower(KEY_TYPE key);
protected KEY_TYPE lowKeyOrNull(Entry KEY_GENERIC_TYPE entry) { return entry == null ? getDefaultMinValue() : entry.key; }
protected KEY_TYPE highKeyOrNull(Entry KEY_GENERIC_TYPE entry) { return entry == null ? getDefaultMaxValue() : entry.key; }
protected abstract Entry KEY_GENERIC_TYPE start();
protected abstract Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry);
@Override final Entry KEY_GENERIC_TYPE absLowest() {
public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); } Entry KEY_GENERIC_TYPE e = (fromStart ? set.first : (loInclusive ? set.findCeilingNode(lo) : set.findHigherNode(lo)));
return (e == null || tooHigh(e.key)) ? null : e;
@Override
public boolean moveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public boolean moveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public COMPARATOR KEY_GENERIC_TYPE comparator() { return set.comparator(); }
@Override
public abstract BI_ITERATOR KEY_GENERIC_TYPE iterator();
@Override
public KEY_TYPE FIRST_KEY() {
Entry KEY_GENERIC_TYPE entry = findLowest();
return entry == null ? getDefaultMaxValue() : entry.key;
} }
protected Entry KEY_GENERIC_TYPE findLowest() { final Entry KEY_GENERIC_TYPE absHighest() {
if(fromStart) return set.first; Entry KEY_GENERIC_TYPE e = (toEnd ? set.last : (hiInclusive ? set.findFloorNode(hi) : set.findLowerNode(hi)));
Entry KEY_GENERIC_TYPE entry = loInclusive ? set.findCeilingNode(start) : set.findHigherNode(start); return (e == null || tooLow(e.key)) ? null : e;
return entry == null || tooHigh(entry.key) ? null : entry;
} }
@Override final Entry KEY_GENERIC_TYPE absCeiling(KEY_TYPE key) {
public KEY_TYPE POLL_FIRST_KEY() { if (tooLow(key)) return absLowest();
if(fromStart) return set.POLL_FIRST_KEY(); Entry KEY_GENERIC_TYPE e = set.findCeilingNode(key);
Entry KEY_GENERIC_TYPE entry = loInclusive ? set.findCeilingNode(start) : set.findHigherNode(start); return (e == null || tooHigh(e.key)) ? null : e;
if(entry != null && !tooHigh(entry.key)) {
KEY_TYPE value = entry.key;
set.removeNode(entry);
return value;
}
return getDefaultMaxValue();
} }
@Override final Entry KEY_GENERIC_TYPE absHigher(KEY_TYPE key) {
public KEY_TYPE LAST_KEY() { if (tooLow(key)) return absLowest();
Entry KEY_GENERIC_TYPE entry = findHighest(); Entry KEY_GENERIC_TYPE e = set.findHigherNode(key);
return entry == null ? getDefaultMinValue() : entry.key; return (e == null || tooHigh(e.key)) ? null : e;
} }
protected Entry KEY_GENERIC_TYPE findHighest() { final Entry KEY_GENERIC_TYPE absFloor(KEY_TYPE key) {
if(toEnd) return set.last; if (tooHigh(key)) return absHighest();
Entry KEY_GENERIC_TYPE entry = hiInclusive ? set.findFloorNode(end) : set.findLowerNode(end); Entry KEY_GENERIC_TYPE e = set.findFloorNode(key);
return entry == null || tooLow(entry.key) ? null : entry; return (e == null || tooLow(e.key)) ? null : e;
} }
@Override final Entry KEY_GENERIC_TYPE absLower(KEY_TYPE key) {
public KEY_TYPE POLL_LAST_KEY() { if (tooHigh(key)) return absHighest();
if(toEnd) return set.POLL_LAST_KEY(); Entry KEY_GENERIC_TYPE e = set.findLowerNode(key);
Entry KEY_GENERIC_TYPE entry = hiInclusive ? set.findFloorNode(end) : set.findLowerNode(end); return (e == null || tooLow(e.key)) ? null : e;
if(entry != null && !tooLow(entry.key)) {
KEY_TYPE value = entry.key;
set.removeNode(entry);
return value;
}
return getDefaultMinValue();
} }
final Entry KEY_GENERIC_TYPE absHighFence() { return (toEnd ? null : (hiInclusive ? set.findHigherNode(hi) : set.findCeilingNode(hi))); }
final Entry KEY_GENERIC_TYPE absLowFence() { return (fromStart ? null : (loInclusive ? set.findLowerNode(lo) : set.findFloorNode(lo))); }
@Override @Override
public boolean add(KEY_TYPE o) { public boolean add(KEY_TYPE o) {
if(!inRange(o)) throw new IllegalArgumentException("Key is out of range"); if(!inRange(o)) throw new IllegalArgumentException("Key is out of range");
@ -1025,50 +1044,85 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
} }
@Override @Override
public KEY_TYPE lower(KEY_TYPE e) { public boolean isEmpty() {
if(tooHigh(e)) { if(fromStart && toEnd) return set.isEmpty();
Entry KEY_GENERIC_TYPE entry = findHighest(); Entry KEY_GENERIC_TYPE n = absLowest();
return entry == null ? getDefaultMinValue() : entry.key; return n == null || tooHigh(n.key);
}
Entry KEY_GENERIC_TYPE entry = set.findLowerNode(e);
return entry == null || tooHigh(entry.key) ? getDefaultMaxValue() : entry.key;
}
@Override
public KEY_TYPE floor(KEY_TYPE e) {
if(tooHigh(e)) {
Entry KEY_GENERIC_TYPE entry = findHighest();
return entry == null ? getDefaultMinValue() : entry.key;
}
Entry KEY_GENERIC_TYPE entry = set.findFloorNode(e);
return entry == null || tooHigh(entry.key) ? getDefaultMaxValue() : entry.key;
}
@Override
public KEY_TYPE ceiling(KEY_TYPE e) {
if(tooLow(e)) {
Entry KEY_GENERIC_TYPE entry = findLowest();
return entry == null ? getDefaultMaxValue() : entry.key;
}
Entry KEY_GENERIC_TYPE entry = set.findCeilingNode(e);
return entry == null || tooLow(entry.key) ? getDefaultMinValue() : entry.key;
}
@Override
public KEY_TYPE higher(KEY_TYPE e) {
if(tooLow(e)) {
Entry KEY_GENERIC_TYPE entry = findLowest();
return entry == null ? getDefaultMaxValue() : entry.key;
}
Entry KEY_GENERIC_TYPE entry = set.findHigherNode(e);
return entry == null || tooLow(entry.key) ? getDefaultMinValue() : entry.key;
} }
@Override @Override
public int size() { public int size() {
return fromStart && toEnd ? set.size() : iterator().skip(Integer.MAX_VALUE); if(fromStart && toEnd) return set.size();
int i = 0;
for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();iter.NEXT(),i++);
return i;
} }
@Override
public KEY_TYPE lower(KEY_TYPE e) {
return lowKeyOrNull(subLower(e));
}
@Override
public KEY_TYPE floor(KEY_TYPE e) {
return lowKeyOrNull(subFloor(e));
}
@Override
public KEY_TYPE ceiling(KEY_TYPE e) {
return highKeyOrNull(subCeiling(e));
}
@Override
public KEY_TYPE higher(KEY_TYPE e) {
return highKeyOrNull(subHigher(e));
}
@Override
public KEY_TYPE POLL_FIRST_KEY() {
Entry KEY_GENERIC_TYPE entry = subLowest();
if(entry != null) {
KEY_TYPE result = entry.key;
set.removeNode(entry);
return result;
}
return getDefaultMinValue();
}
@Override
public KEY_TYPE POLL_LAST_KEY() {
Entry KEY_GENERIC_TYPE entry = subHighest();
if(entry != null) {
KEY_TYPE result = entry.key;
set.removeNode(entry);
return result;
}
return getDefaultMaxValue();
}
@Override
public KEY_TYPE FIRST_KEY() {
Entry KEY_GENERIC_TYPE entry = subLowest();
if(entry == null) throw new NoSuchElementException();
return entry.key;
}
@Override
public KEY_TYPE LAST_KEY() {
Entry KEY_GENERIC_TYPE entry = subHighest();
if(entry == null) throw new NoSuchElementException();
return entry.key;
}
@Override
public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public boolean moveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public boolean moveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override @Override
public SubSet KEY_GENERIC_TYPE copy() { throw new UnsupportedOperationException(); } public SubSet KEY_GENERIC_TYPE copy() { throw new UnsupportedOperationException(); }
@ -1172,16 +1226,124 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
return result; return result;
} }
class SubSetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE class AscendingSubSetIterator implements BI_ITERATOR KEY_GENERIC_TYPE
{ {
Entry KEY_GENERIC_TYPE previous; Entry KEY_GENERIC_TYPE lastReturned;
Entry KEY_GENERIC_TYPE next; Entry KEY_GENERIC_TYPE next;
Entry KEY_GENERIC_TYPE current; boolean unboundForwardFence;
int index = 0; boolean unboundBackwardFence;
KEY_TYPE forwardFence;
KEY_TYPE backwardFence;
public SubSetIterator(Entry KEY_GENERIC_TYPE entry) { public AscendingSubSetIterator(Entry KEY_GENERIC_TYPE first, Entry KEY_GENERIC_TYPE forwardFence, Entry KEY_GENERIC_TYPE backwardFence)
next = entry; {
previous = entry == null ? null : entry.previous(); next = 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;
}
@Override
public boolean hasNext() {
return next != null && (unboundForwardFence || next.key != forwardFence);
}
@Override
public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException();
lastReturned = next;
KEY_TYPE result = next.key;
next = next.next();
return result;
}
@Override
public boolean hasPrevious() {
return next != null && (unboundBackwardFence || next.key != backwardFence);
}
@Override
public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException();
lastReturned = next;
KEY_TYPE result = next.key;
next = next.previous();
return result;
}
@Override
public void remove() {
if(lastReturned == null) throw new IllegalStateException();
if(lastReturned.needsSuccessor()) next = lastReturned;
set.removeNode(lastReturned);
lastReturned = null;
}
}
class DescendingSubSetIterator implements BI_ITERATOR KEY_GENERIC_TYPE
{
Entry KEY_GENERIC_TYPE lastReturned;
Entry KEY_GENERIC_TYPE next;
boolean unboundForwardFence;
boolean unboundBackwardFence;
KEY_TYPE forwardFence;
KEY_TYPE backwardFence;
public DescendingSubSetIterator(Entry KEY_GENERIC_TYPE first, Entry KEY_GENERIC_TYPE forwardFence, Entry KEY_GENERIC_TYPE backwardFence)
{
next = 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;
}
@Override
public boolean hasNext() {
return next != null && (unboundForwardFence || next.key != forwardFence);
}
@Override
public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException();
lastReturned = next;
KEY_TYPE result = next.key;
next = next.previous();
return result;
}
@Override
public boolean hasPrevious() {
return next != null && (unboundBackwardFence || next.key != backwardFence);
}
@Override
public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException();
lastReturned = next;
KEY_TYPE result = next.key;
next = next.next();
return result;
}
@Override
public void remove() {
if(lastReturned == null) throw new IllegalStateException();
set.removeNode(lastReturned);
lastReturned = null;
}
}
}
class AscendingSetIterator implements BI_ITERATOR KEY_GENERIC_TYPE
{
Entry KEY_GENERIC_TYPE lastReturned;
Entry KEY_GENERIC_TYPE next;
public AscendingSetIterator(Entry KEY_GENERIC_TYPE first)
{
next = first;
} }
@Override @Override
@ -1189,90 +1351,46 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
return next != null; return next != null;
} }
@Override
public boolean hasPrevious() {
return previous != null;
}
@Override
public int nextIndex() {
return index;
}
@Override
public int previousIndex() {
return index - 1;
}
boolean topReached(Entry KEY_GENERIC_TYPE entry) {
return hiInclusive ? set.compare(entry.key, end) >= 0 : set.compare(entry.key, end) > 0;
}
boolean bottomReached(Entry KEY_GENERIC_TYPE entry) {
return loInclusive ? set.compare(entry.key, start) <= 0 : set.compare(entry.key, start) < 0;
}
protected void updateNext() {
next = current.next();
if(!toEnd && next != null && topReached(next)) next = null;
}
protected void updatePrevious() {
previous = current.previous();
if(!fromStart && previous != null && bottomReached(previous)) previous = null;
}
@Override @Override
public KEY_TYPE NEXT() { public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException(); if(!hasNext()) throw new NoSuchElementException();
current = previous = next; lastReturned = next;
updateNext(); KEY_TYPE result = next.key;
index++; next = next.next();
return current.key; return result;
}
@Override
public boolean hasPrevious() {
return next != null;
} }
@Override @Override
public KEY_TYPE PREVIOUS() { public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException(); if(!hasPrevious()) throw new NoSuchElementException();
current = next = previous; lastReturned = next;
updatePrevious(); KEY_TYPE result = next.key;
index--; next = next.previous();
return current.key; return result;
} }
@Override @Override
public void remove() { public void remove() {
if(current == null) throw new IllegalStateException(); if(lastReturned == null) throw new IllegalStateException();
if(current == previous) index--; if(lastReturned.needsSuccessor()) next = lastReturned;
updateNext(); removeNode(lastReturned);
updatePrevious(); lastReturned = null;
set.removeNode(current);
current = null;
}
@Override
public void set(KEY_TYPE e){ throw new UnsupportedOperationException(); }
@Override
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
} }
} }
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE class DescendingSetIterator implements BI_ITERATOR KEY_GENERIC_TYPE
{ {
Entry KEY_GENERIC_TYPE previous; Entry KEY_GENERIC_TYPE lastReturned;
Entry KEY_GENERIC_TYPE next; Entry KEY_GENERIC_TYPE next;
Entry KEY_GENERIC_TYPE current;
int index = 0;
public SetIterator(boolean descending) { public DescendingSetIterator(Entry KEY_GENERIC_TYPE first)
if(descending) previous = last; {
else next = first; next = first;
}
public SetIterator(Entry KEY_GENERIC_TYPE entry) {
next = entry;
previous = entry.previous();
} }
@Override @Override
@ -1280,63 +1398,35 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
return next != null; return next != null;
} }
@Override
public boolean hasPrevious() {
return previous != null;
}
@Override
public int nextIndex() {
return index;
}
@Override
public int previousIndex() {
return index - 1;
}
protected void updateNext() {
next = current.next();
}
protected void updatePrevious() {
previous = current.previous();
}
@Override @Override
public KEY_TYPE NEXT() { public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException(); if(!hasNext()) throw new NoSuchElementException();
current = previous = next; lastReturned = next;
updateNext(); KEY_TYPE result = next.key;
index++; next = next.previous();
return current.key; return result;
}
@Override
public boolean hasPrevious() {
return next != null;
} }
@Override @Override
public KEY_TYPE PREVIOUS() { public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException(); if(!hasPrevious()) throw new NoSuchElementException();
current = next = previous; lastReturned = next;
updatePrevious(); KEY_TYPE result = next.key;
index--; next = next.next();
return current.key; return result;
} }
@Override @Override
public void remove() { public void remove() {
if(current == null) throw new IllegalStateException(); if(lastReturned == null) throw new IllegalStateException();
if(current == previous) index--; removeNode(lastReturned);
updateNext(); lastReturned = null;
updatePrevious();
if(current.needsSuccessor()) next = current;
removeNode(current);
current = null;
} }
@Override
public void set(KEY_TYPE e){ throw new UnsupportedOperationException(); }
@Override
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
} }
private static final class Entry KEY_GENERIC_TYPE private static final class Entry KEY_GENERIC_TYPE

View File

@ -499,27 +499,30 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
/**
* Unsupported for now. Implementation is buggy and does not support the Java Standard with these functions.
* It is a Unsorted Sorted Set. Thats why the SubSet implementation will be disabled until a better solution is found.
* To give a simple reason: LinkedHashSets are also not SortedSets even so they could be.
* @throws UnsupportedOperationException
*/
@Override @Override
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
int fromIndex = findIndex(fromElement); /**
int toIndex = findIndex(toElement); * Unsupported for now. Implementation is buggy and does not support the Java Standard with these functions.
if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException(); * It is a Unsorted Sorted Set. Thats why the SubSet implementation will be disabled until a better solution is found.
return new SubSet(fromIndex, toIndex - fromIndex + 1); * To give a simple reason: LinkedHashSets are also not SortedSets even so they could be.
} * @throws UnsupportedOperationException
*/
@Override @Override
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
int toIndex = findIndex(toElement); /**
if(toIndex == -1) throw new NoSuchElementException(); * Unsupported for now. Implementation is buggy and does not support the Java Standard with these functions.
return new SubSet(0, toIndex+1); * It is a Unsorted Sorted Set. Thats why the SubSet implementation will be disabled until a better solution is found.
} * To give a simple reason: LinkedHashSets are also not SortedSets even so they could be.
* @throws UnsupportedOperationException
*/
@Override @Override
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { throw new UnsupportedOperationException(); }
int fromIndex = findIndex(fromElement);
if(fromIndex == -1) throw new NoSuchElementException();
return new SubSet(fromIndex, size - fromIndex);
}
public ARRAY_SET KEY_GENERIC_TYPE copy() { public ARRAY_SET KEY_GENERIC_TYPE copy() {
ARRAY_SET KEY_GENERIC_TYPE set = new ARRAY_SETBRACES(); ARRAY_SET KEY_GENERIC_TYPE set = new ARRAY_SETBRACES();
@ -573,345 +576,346 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
return a; return a;
} }
private class SubSet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE { // Disabled until a Proper Implementation can be thought out or it is decided that the interface is thrown out.
int offset; // private class SubSet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
int length; // int offset;
// int length;
SubSet(int offset, int length) { //
this.offset = offset; // SubSet(int offset, int length) {
this.length = length; // this.offset = offset;
} // this.length = length;
// }
int end() { return offset+length; } //
// int end() { return offset+length; }
@Override //
public boolean add(KEY_TYPE o) { // @Override
int index = findIndex(o); // public boolean add(KEY_TYPE o) {
if(index == -1) { // int index = findIndex(o);
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2); // if(index == -1) {
if(end() != size) System.arraycopy(data, end(), data, end()+1, size-(offset+length)); // if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
data[end()] = o; // if(end() != size) System.arraycopy(data, end(), data, end()+1, size-(offset+length));
size++; // data[end()] = o;
length++; // size++;
return true; // length++;
} // return true;
return false; // }
} // return false;
// }
@Override //
public boolean addAndMoveToFirst(KEY_TYPE o) { // @Override
int index = findIndex(o); // public boolean addAndMoveToFirst(KEY_TYPE o) {
if(index == -1) { // int index = findIndex(o);
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2); // if(index == -1) {
System.arraycopy(data, offset, data, offset+1, size-offset); // if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
data[offset] = o; // System.arraycopy(data, offset, data, offset+1, size-offset);
size++; // data[offset] = o;
length++; // size++;
return true; // length++;
} // return true;
else if(index != 0) { // }
o = data[index]; // else if(index != 0) {
System.arraycopy(data, offset, data, offset+1, index-offset); // o = data[index];
data[offset] = o; // System.arraycopy(data, offset, data, offset+1, index-offset);
} // data[offset] = o;
return false; // }
} // return false;
// }
@Override //
public boolean addAndMoveToLast(KEY_TYPE o) { // @Override
int index = findIndex(o); // public boolean addAndMoveToLast(KEY_TYPE o) {
if(index == -1) { // int index = findIndex(o);
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2); // if(index == -1) {
System.arraycopy(data, end()+1, data, end(), size-end()); // if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
data[end()] = o; // System.arraycopy(data, end()+1, data, end(), size-end());
size++; // data[end()] = o;
length++; // size++;
return true; // length++;
} // return true;
else if(index != 0) { // }
o = data[index]; // else if(index != 0) {
System.arraycopy(data, offset+1, data, offset, index-offset); // o = data[index];
data[offset+length] = o; // System.arraycopy(data, offset+1, data, offset, index-offset);
} // data[offset+length] = o;
return false; // }
} // return false;
// }
@Override //
public boolean moveToFirst(KEY_TYPE o) { // @Override
int index = findIndex(o); // public boolean moveToFirst(KEY_TYPE o) {
if(index > offset) { // int index = findIndex(o);
o = data[index]; // if(index > offset) {
System.arraycopy(data, offset, data, offset+1, index-offset); // o = data[index];
data[offset] = o; // System.arraycopy(data, offset, data, offset+1, index-offset);
return true; // data[offset] = o;
} // return true;
return false; // }
} // return false;
// }
@Override //
public boolean moveToLast(KEY_TYPE o) { // @Override
int index = findIndex(o); // public boolean moveToLast(KEY_TYPE o) {
if(index != -1 && index < end()-1) { // int index = findIndex(o);
o = data[index]; // if(index != -1 && index < end()-1) {
System.arraycopy(data, index+1, data, index, end()-index-1); // o = data[index];
data[end()-1] = o; // System.arraycopy(data, index+1, data, index, end()-index-1);
return true; // data[end()-1] = o;
} // return true;
return false; // }
} // return false;
// }
#if !TYPE_OBJECT //
@Override //#if !TYPE_OBJECT
public boolean contains(KEY_TYPE e) { // @Override
return findIndex(e) != -1; // public boolean contains(KEY_TYPE e) {
} // return findIndex(e) != -1;
// }
#endif //
@Override //#endif
public boolean contains(Object e) { // @Override
return findIndex(e) != -1; // public boolean contains(Object e) {
} // return findIndex(e) != -1;
// }
@Override //
public KEY_TYPE FIRST_KEY() { // @Override
if(length == 0) throw new NoSuchElementException(); // public KEY_TYPE FIRST_KEY() {
return data[offset]; // if(length == 0) throw new NoSuchElementException();
} // return data[offset];
// }
@Override //
public KEY_TYPE LAST_KEY() { // @Override
if(length == 0) throw new NoSuchElementException(); // public KEY_TYPE LAST_KEY() {
return data[end()-1]; // if(length == 0) throw new NoSuchElementException();
} // return data[end()-1];
// }
#if !TYPE_OBJECT //
@Override //#if !TYPE_OBJECT
public boolean remove(KEY_TYPE o) { // @Override
int index = findIndex(o); // public boolean remove(KEY_TYPE o) {
if(index != -1) { // int index = findIndex(o);
size--; // if(index != -1) {
length--; // size--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index); // length--;
return true; // if(index != size) System.arraycopy(data, index+1, data, index, size - index);
} // return true;
return false; // }
} // return false;
// }
#endif //
@Override //#endif
public boolean remove(Object o) { // @Override
int index = findIndex(o); // public boolean remove(Object o) {
if(index != -1) { // int index = findIndex(o);
size--; // if(index != -1) {
length--; // size--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index); // length--;
#if TYPE_OBJECT // if(index != size) System.arraycopy(data, index+1, data, index, size - index);
data[size] = EMPTY_KEY_VALUE; //#if TYPE_OBJECT
#endif // data[size] = EMPTY_KEY_VALUE;
return true; //#endif
} // return true;
return false; // }
} // return false;
// }
@Override //
public KEY_TYPE POLL_FIRST_KEY() { // @Override
if(length == 0) throw new NoSuchElementException(); // public KEY_TYPE POLL_FIRST_KEY() {
size--; // if(length == 0) throw new NoSuchElementException();
length--; // size--;
KEY_TYPE result = data[offset]; // length--;
System.arraycopy(data, offset+1, data, offset, size-offset); // KEY_TYPE result = data[offset];
#if TYPE_OBJECT // System.arraycopy(data, offset+1, data, offset, size-offset);
data[size] = EMPTY_KEY_VALUE; //#if TYPE_OBJECT
#endif // data[size] = EMPTY_KEY_VALUE;
return result; //#endif
} // return result;
// }
@Override //
public KEY_TYPE POLL_LAST_KEY() { // @Override
if(length == 0) throw new NoSuchElementException(); // public KEY_TYPE POLL_LAST_KEY() {
KEY_TYPE result = data[offset+length]; // if(length == 0) throw new NoSuchElementException();
size--; // KEY_TYPE result = data[offset+length];
length--; // size--;
System.arraycopy(data, end()+1, data, end(), size-end()); // length--;
#if TYPE_OBJECT // System.arraycopy(data, end()+1, data, end(), size-end());
data[size] = EMPTY_KEY_VALUE; //#if TYPE_OBJECT
#endif // data[size] = EMPTY_KEY_VALUE;
return result; //#endif
} // return result;
// }
@Override //
public COMPARATOR KEY_GENERIC_TYPE comparator() { // @Override
return null; // public COMPARATOR KEY_GENERIC_TYPE comparator() {
} // return null;
// }
@Override //
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { // @Override
return new SetIterator(offset); // public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
} // return new SetIterator(offset);
// }
@Override //
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) { // @Override
int index = findIndex(fromElement); // public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
if(index != -1) return new SetIterator(index); // int index = findIndex(fromElement);
throw new NoSuchElementException(); // if(index != -1) return new SetIterator(index);
} // throw new NoSuchElementException();
// }
@Override //
public SubSet copy() { throw new UnsupportedOperationException(); } // @Override
// public SubSet copy() { throw new UnsupportedOperationException(); }
@Override //
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { // @Override
int fromIndex = findIndex(fromElement); // public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) {
int toIndex = findIndex(toElement); // int fromIndex = findIndex(fromElement);
if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException(); // int toIndex = findIndex(toElement);
return new SubSet(fromIndex, toIndex - fromIndex + 1); // if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException();
} // return new SubSet(fromIndex, toIndex - fromIndex + 1);
// }
@Override //
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { // @Override
int toIndex = findIndex(toElement); // public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) {
if(toIndex == -1) throw new NoSuchElementException(); // int toIndex = findIndex(toElement);
return new SubSet(0, toIndex+1); // if(toIndex == -1) throw new NoSuchElementException();
} // return new SubSet(0, toIndex+1);
// }
@Override //
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { // @Override
int fromIndex = findIndex(fromElement); // public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) {
if(fromIndex == -1) throw new NoSuchElementException(); // int fromIndex = findIndex(fromElement);
return new SubSet(fromIndex, size - fromIndex); // if(fromIndex == -1) throw new NoSuchElementException();
} // return new SubSet(fromIndex, size - fromIndex);
// }
@Override //
public int size() { // @Override
return length; // public int size() {
} // return length;
// }
#if !TYPE_OBJECT //
@Override //#if !TYPE_OBJECT
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) { // @Override
if(a == null || a.length < size()) return Arrays.copyOfRange(data, offset, end()); // public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
System.arraycopy(data, offset, a, 0, size()); // if(a == null || a.length < size()) return Arrays.copyOfRange(data, offset, end());
return a; // System.arraycopy(data, offset, a, 0, size());
} // return a;
// }
#endif //
@Override //#endif
@Deprecated // @Override
public Object[] toArray() { // @Deprecated
Object[] obj = new Object[size()]; // public Object[] toArray() {
for(int i = 0;i<size();i++) // Object[] obj = new Object[size()];
obj[i] = KEY_TO_OBJ(data[offset+i]); // for(int i = 0;i<size();i++)
return obj; // obj[i] = KEY_TO_OBJ(data[offset+i]);
} // return obj;
// }
@Override //
@Primitive // @Override
public <E> E[] toArray(E[] a) { // @Primitive
if(a == null) a = (E[])new Object[size()]; // public <E> E[] toArray(E[] a) {
else if(a.length < size()) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), size()); // if(a == null) a = (E[])new Object[size()];
for(int i = 0;i<size();i++) // else if(a.length < size()) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), size());
a[i] = (E)KEY_TO_OBJ(data[offset+i]); // for(int i = 0;i<size();i++)
return a; // a[i] = (E)KEY_TO_OBJ(data[offset+i]);
} // return a;
// }
#if !TYPE_OBJECT //
protected int findIndex(KEY_TYPE o) { //#if !TYPE_OBJECT
for(int i = length-1;i>=0;i--) // protected int findIndex(KEY_TYPE o) {
if(KEY_EQUALS(data[offset+i], o)) return i + offset; // for(int i = length-1;i>=0;i--)
return -1; // if(KEY_EQUALS(data[offset+i], o)) return i + offset;
} // return -1;
// }
#endif //
protected int findIndex(Object o) { //#endif
for(int i = length-1;i>=0;i--) // protected int findIndex(Object o) {
if(EQUALS_KEY_TYPE(data[offset+i], o)) return i + offset; // for(int i = length-1;i>=0;i--)
return -1; // if(EQUALS_KEY_TYPE(data[offset+i], o)) return i + offset;
} // return -1;
// }
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE { //
int index; // private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
int lastReturned = -1; // int index;
// int lastReturned = -1;
public SetIterator(int index) { //
this.index = index; // public SetIterator(int index) {
} // this.index = index;
// }
@Override //
public boolean hasNext() { // @Override
return index < size(); // public boolean hasNext() {
} // return index < size();
// }
@Override //
public KEY_TYPE NEXT() { // @Override
if(!hasNext()) throw new NoSuchElementException(); // public KEY_TYPE NEXT() {
lastReturned = index; // if(!hasNext()) throw new NoSuchElementException();
return data[index++]; // lastReturned = index;
} // return data[index++];
// }
@Override //
public boolean hasPrevious() { // @Override
return index > 0; // public boolean hasPrevious() {
} // return index > 0;
// }
@Override //
public KEY_TYPE PREVIOUS() { // @Override
if(!hasPrevious()) throw new NoSuchElementException(); // public KEY_TYPE PREVIOUS() {
lastReturned = index; // if(!hasPrevious()) throw new NoSuchElementException();
return data[index--]; // lastReturned = index;
} // return data[index--];
// }
@Override //
public int nextIndex() { // @Override
return index; // public int nextIndex() {
} // return index;
// }
@Override //
public int previousIndex() { // @Override
return index-1; // public int previousIndex() {
} // return index-1;
// }
@Override //
public void remove() { // @Override
if(lastReturned == -1) // public void remove() {
throw new IllegalStateException(); // if(lastReturned == -1)
SubSet.this.remove(data[lastReturned]); // throw new IllegalStateException();
if(lastReturned < index) // SubSet.this.remove(data[lastReturned]);
index--; // if(lastReturned < index)
lastReturned = -1; // index--;
} // lastReturned = -1;
// }
#if TYPE_OBJECT //
@Override // #if TYPE_OBJECT
public void set(Object e) { throw new UnsupportedOperationException(); } // @Override
// public void set(Object e) { throw new UnsupportedOperationException(); }
@Override //
public void add(Object e) { throw new UnsupportedOperationException(); } // @Override
// public void add(Object e) { throw new UnsupportedOperationException(); }
#else //
@Override // #else
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); } // @Override
// public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
@Override //
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); } // @Override
// public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
#endif //
@Override // #endif
public int skip(int amount) { // @Override
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed"); // public int skip(int amount) {
int steps = Math.min(amount, (size() - 1) - index); // if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
index += steps; // int steps = Math.min(amount, (size() - 1) - index);
return steps; // index += steps;
} // return steps;
// }
@Override //
public int back(int amount) { // @Override
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed"); // public int back(int amount) {
int steps = Math.min(amount, index); // if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
index -= steps; // int steps = Math.min(amount, index);
return steps; // index -= steps;
} // return steps;
} // }
} // }
// }
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE { private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
int index; int index;

View File

@ -1,6 +1,7 @@
package speiger.src.collections.PACKAGE.sets; package speiger.src.collections.PACKAGE.sets;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
#if TYPE_OBJECT #if TYPE_OBJECT
import java.util.Comparator; import java.util.Comparator;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -19,7 +20,6 @@ import speiger.src.collections.PACKAGE.functions.function.PREDICATE;
import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR; import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR;
import speiger.src.collections.PACKAGE.collections.COLLECTION; import speiger.src.collections.PACKAGE.collections.COLLECTION;
import speiger.src.collections.PACKAGE.collections.ITERATOR; import speiger.src.collections.PACKAGE.collections.ITERATOR;
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
#if !TYPE_OBJECT #if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.utils.ITERATORS; import speiger.src.collections.PACKAGE.utils.ITERATORS;
#endif #endif
@ -559,7 +559,11 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
@Override @Override
public KEY_TYPE POLL_FIRST_KEY() { public KEY_TYPE POLL_FIRST_KEY() {
if(tree == null) throw new NoSuchElementException(); #if TYPE_OBJECT
if(tree == null) return null;
#else
if(tree == null) return getDefaultMinValue();
#endif
KEY_TYPE value = first.key; KEY_TYPE value = first.key;
removeNode(first); removeNode(first);
return value; return value;
@ -567,7 +571,11 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
@Override @Override
public KEY_TYPE POLL_LAST_KEY() { public KEY_TYPE POLL_LAST_KEY() {
if(tree == null) throw new NoSuchElementException(); #if TYPE_OBJECT
if(tree == null) return null;
#else
if(tree == null) return getDefaultMaxValue();
#endif
KEY_TYPE value = last.key; KEY_TYPE value = last.key;
removeNode(last); removeNode(last);
return value; return value;
@ -603,16 +611,16 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; } public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return new SetIterator(false); } public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return new AscendingSetIterator(first); }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) { public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
Entry KEY_GENERIC_TYPE entry = findNode(fromElement); Entry KEY_GENERIC_TYPE entry = findNode(fromElement);
return entry == null ? null : new SetIterator(entry); return entry == null ? null : new AscendingSetIterator(entry);
} }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return new SetIterator(true); } public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return new DescendingSetIterator(last); }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) {
@ -804,158 +812,174 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
setBlack(entry, true); setBlack(entry, true);
} }
private static class AscendingSubSet KEY_GENERIC_TYPE extends SubSet KEY_GENERIC_TYPE static class AscendingSubSet KEY_GENERIC_TYPE extends SubSet KEY_GENERIC_TYPE
{ {
AscendingSubSet(RB_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE start, boolean loInclusive, boolean toEnd, KEY_TYPE end, boolean hiInclusive) { public AscendingSubSet(RB_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE lo, boolean loInclusive, boolean toEnd, KEY_TYPE hi, boolean hiInclusive)
super(set, fromStart, start, loInclusive, toEnd, end, hiInclusive); {
super(set, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) { public COMPARATOR KEY_GENERIC_TYPE comparator() { return set.comparator(); }
if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement is not in Range");
if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement is not in Range"); @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive)
{
if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement out of range");
if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement out of range");
return new AscendingSubSetBRACES(set, false, fromElement, fromInclusive, false, toElement, toInclusive); return new AscendingSubSetBRACES(set, false, fromElement, fromInclusive, false, toElement, toInclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive)
if(!inRange(toElement, inclusive)) throw new IllegalArgumentException("toElement is not in Range"); {
return new AscendingSubSetBRACES(set, fromStart, start, loInclusive, false, toElement, inclusive); if(!inRange(toElement, inclusive)) throw new IllegalArgumentException("toElement out of range");
return new AscendingSubSetBRACES(set, fromStart, lo, loInclusive, false, toElement, inclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive)
if(!inRange(fromElement, inclusive)) throw new IllegalArgumentException("fromElement is not in Range"); {
return new AscendingSubSetBRACES(set, false, fromElement, inclusive, toEnd, end, hiInclusive); if(!inRange(fromElement, inclusive)) throw new IllegalArgumentException("fromElement out of range");
return new AscendingSubSetBRACES(set, false, fromElement, inclusive, toEnd, hi, hiInclusive);
} }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return new SubSetIterator(findLowest()); } public BI_ITERATOR KEY_GENERIC_TYPE iterator()
{
@Override return new AscendingSubSetIterator(absLowest(), absHighFence(), absLowFence());
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
Entry KEY_GENERIC_TYPE entry = set.findNode(fromElement);
return entry == null || !inClosedRange(fromElement) ? null : new SubSetIterator(entry);
} }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return new SubSetIterator(findHighest()); } public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement)
{
return new AscendingSubSetIterator(absLower(fromElement), absHighFence(), absLowFence());
}
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() { public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator()
return new DescendingSubSetBRACES(set, fromStart, start, loInclusive, toEnd, end, hiInclusive); {
} return new DescendingSubSetIterator(absHighest(), absLowFence(), absHighFence());
} }
private static class DescendingSubSet KEY_GENERIC_TYPE extends SubSet KEY_GENERIC_TYPE @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet()
{
if(inverse == null) inverse = new DescendingSubSetBRACES(set, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
return inverse;
}
@Override
protected Entry KEY_GENERIC_TYPE subLowest() { return absLowest(); }
@Override
protected Entry KEY_GENERIC_TYPE subHighest() { return absHighest(); }
@Override
protected Entry KEY_GENERIC_TYPE subCeiling(KEY_TYPE key) { return absCeiling(key); }
@Override
protected Entry KEY_GENERIC_TYPE subHigher(KEY_TYPE key) { return absHigher(key); }
@Override
protected Entry KEY_GENERIC_TYPE subFloor(KEY_TYPE key) { return absFloor(key); }
@Override
protected Entry KEY_GENERIC_TYPE subLower(KEY_TYPE key) { return absLower(key); }
@Override
protected Entry KEY_GENERIC_TYPE start() { return absLowest(); }
@Override
protected Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry) { return entry.next(); }
}
static class DescendingSubSet KEY_GENERIC_TYPE extends SubSet KEY_GENERIC_TYPE
{ {
COMPARATOR KEY_GENERIC_TYPE comparator; COMPARATOR KEY_GENERIC_TYPE comparator;
DescendingSubSet(RB_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE start, boolean loInclusive, boolean toEnd, KEY_TYPE end, boolean hiInclusive) {
super(set, fromStart, start, loInclusive, toEnd, end, hiInclusive); public DescendingSubSet(RB_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE lo, boolean loInclusive, boolean toEnd, KEY_TYPE hi, boolean hiInclusive)
comparator = set.comparator(); {
if(comparator != null) comparator = comparator.reversed(); super(set, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
#if TYPE_OBJECT
comparator = Collections.reverseOrder(set.comparator());
#else
comparator = set.comparator() == null ? COMPARATOR.of(Collections.reverseOrder()) : set.comparator().reversed();
#endif
} }
@Override @Override
public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; } public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; }
public KEY_TYPE getDefaultMaxValue() { return super.getDefaultMinValue(); }
public KEY_TYPE getDefaultMinValue() { return super.getDefaultMaxValue(); }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) {
if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement is not in Range"); if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement out of range");
if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement is not in Range"); if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement out of range");
return new DescendingSubSetBRACES(set, false, toElement, toInclusive, false, fromElement, fromInclusive); return new DescendingSubSetBRACES(set, false, fromElement, fromInclusive, false, toElement, toInclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive)
if(!inRange(toElement, inclusive)) throw new IllegalArgumentException("toElement is not in Range"); {
return new DescendingSubSetBRACES(set, false, toElement, inclusive, toEnd, end, hiInclusive); if(!inRange(toElement, inclusive)) throw new IllegalArgumentException("toElement out of range");
return new DescendingSubSetBRACES(set, false, toElement, inclusive, toEnd, hi, hiInclusive);
} }
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) { public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) {
if(!inRange(fromElement, inclusive)) throw new IllegalArgumentException("fromElement is not in Range"); if(!inRange(fromElement, inclusive)) throw new IllegalArgumentException("fromElement out of range");
return new DescendingSubSetBRACES(set, fromStart, start, loInclusive, false, fromElement, inclusive); return new DescendingSubSetBRACES(set, fromStart, lo, loInclusive, false, fromElement, inclusive);
}
protected Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry) { return entry.previous(); }
protected Entry KEY_GENERIC_TYPE start() { return findHighest(); }
@Override
public KEY_TYPE FIRST_KEY() { return super.LAST_KEY(); }
@Override
public KEY_TYPE POLL_FIRST_KEY() { return super.POLL_LAST_KEY(); }
@Override
public KEY_TYPE LAST_KEY() { return super.FIRST_KEY(); }
@Override
public KEY_TYPE POLL_LAST_KEY() { return super.POLL_FIRST_KEY(); }
@Override
public KEY_TYPE lower(KEY_TYPE e) { return super.higher(e); }
@Override
public KEY_TYPE floor(KEY_TYPE e) { return super.ceiling(e); }
@Override
public KEY_TYPE ceiling(KEY_TYPE e) { return super.floor(e); }
@Override
public KEY_TYPE higher(KEY_TYPE e) { return super.lower(e); }
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return new DescendingSubIterator(findHighest()); }
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
Entry KEY_GENERIC_TYPE entry = set.findNode(fromElement);
return entry == null || !inClosedRange(fromElement) ? null : new DescendingSubIterator(entry);
} }
@Override @Override
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return new DescendingSubIterator(findLowest()); } public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
return new DescendingSubSetIterator(absHighest(), absLowFence(), absHighFence());
}
@Override
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() {
return new AscendingSubSetIterator(absLowest(), absHighFence(), absLowFence());
}
@Override @Override
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() { public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() {
return new AscendingSubSetBRACES(set, fromStart, start, loInclusive, toEnd, end, hiInclusive); if(inverse == null) inverse = new AscendingSubSetBRACES(set, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
} return inverse;
private class DescendingSubIterator extends SubSetIterator
{
public DescendingSubIterator(Entry KEY_GENERIC_TYPE entry) {
super(entry);
} }
@Override @Override
protected void updateNext() { public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
next = current.previous(); return new DescendingSubSetIterator(absHigher(fromElement), absLowFence(), absHighFence());
if(!toEnd && next != null && bottomReached(next)) next = null;
} }
@Override @Override
protected void updatePrevious() { protected Entry KEY_GENERIC_TYPE subLowest() { return absHighest(); }
previous = current.next(); @Override
if(!fromStart && previous != null && topReached(previous)) previous = null; protected Entry KEY_GENERIC_TYPE subHighest() { return absLowest(); }
} @Override
} protected Entry KEY_GENERIC_TYPE subCeiling(KEY_TYPE key) { return absFloor(key); }
@Override
protected Entry KEY_GENERIC_TYPE subHigher(KEY_TYPE key) { return absLower(key); }
@Override
protected Entry KEY_GENERIC_TYPE subFloor(KEY_TYPE key) { return absCeiling(key); }
@Override
protected Entry KEY_GENERIC_TYPE subLower(KEY_TYPE key) { return absHigher(key); }
@Override
protected Entry KEY_GENERIC_TYPE start() { return absHighest(); }
@Override
protected Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry) { return entry.previous(); }
} }
private static abstract class SubSet KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE static abstract class SubSet KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE
{ {
RB_TREE_SET KEY_GENERIC_TYPE set; final RB_TREE_SET KEY_GENERIC_TYPE set;
KEY_TYPE start; final KEY_TYPE lo, hi;
KEY_TYPE end; final boolean fromStart, toEnd;
boolean fromStart; final boolean loInclusive, hiInclusive;
boolean toEnd; NAVIGABLE_SET KEY_GENERIC_TYPE inverse;
boolean loInclusive;
boolean hiInclusive;
SubSet(RB_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE start, boolean loInclusive, boolean toEnd, KEY_TYPE end, boolean hiInclusive) { public SubSet(RB_TREE_SET KEY_GENERIC_TYPE set, boolean fromStart, KEY_TYPE lo, boolean loInclusive, boolean toEnd, KEY_TYPE hi, boolean hiInclusive)
{
this.set = set; this.set = set;
this.start = start; this.lo = lo;
this.end = end; this.hi = hi;
this.fromStart = fromStart; this.fromStart = fromStart;
this.toEnd = toEnd; this.toEnd = toEnd;
this.loInclusive = loInclusive; this.loInclusive = loInclusive;
@ -981,80 +1005,75 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
public KEY_TYPE getDefaultMinValue() { return null; } public KEY_TYPE getDefaultMinValue() { return null; }
#endif #endif
boolean tooLow(KEY_TYPE key) { return !fromStart && (loInclusive ? set.compare(key, start) < 0 : set.compare(key, start) <= 0); }
boolean tooHigh(KEY_TYPE key) { return !toEnd && (hiInclusive ? set.compare(key, end) > 0 : set.compare(key, end) >= 0); } boolean tooLow(KEY_TYPE key) {
if (!fromStart) {
int c = set.compare(key, lo);
if (c < 0 || (c == 0 && !loInclusive)) return true;
}
return false;
}
boolean tooHigh(KEY_TYPE key) {
if (!toEnd) {
int c = set.compare(key, hi);
if (c > 0 || (c == 0 && !hiInclusive)) return true;
}
return false;
}
boolean inRange(KEY_TYPE key) { return !tooLow(key) && !tooHigh(key); } boolean inRange(KEY_TYPE key) { return !tooLow(key) && !tooHigh(key); }
boolean inClosedRange(KEY_TYPE key) { return (fromStart || set.compare(key, start) >= 0) && (toEnd || set.compare(end, key) >= 0); } boolean inClosedRange(KEY_TYPE key) { return (fromStart || set.compare(key, lo) >= 0) && (toEnd || set.compare(hi, key) >= 0); }
boolean inRange(KEY_TYPE key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); } boolean inRange(KEY_TYPE key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); }
protected Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry) { return entry.next(); }
protected Entry KEY_GENERIC_TYPE start() { return findLowest(); }
@Override protected abstract Entry KEY_GENERIC_TYPE subLowest();
public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); } protected abstract Entry KEY_GENERIC_TYPE subHighest();
protected abstract Entry KEY_GENERIC_TYPE subCeiling(KEY_TYPE key);
protected abstract Entry KEY_GENERIC_TYPE subHigher(KEY_TYPE key);
protected abstract Entry KEY_GENERIC_TYPE subFloor(KEY_TYPE key);
protected abstract Entry KEY_GENERIC_TYPE subLower(KEY_TYPE key);
protected KEY_TYPE lowKeyOrNull(Entry KEY_GENERIC_TYPE entry) { return entry == null ? getDefaultMinValue() : entry.key; }
protected KEY_TYPE highKeyOrNull(Entry KEY_GENERIC_TYPE entry) { return entry == null ? getDefaultMaxValue() : entry.key; }
protected abstract Entry KEY_GENERIC_TYPE start();
protected abstract Entry KEY_GENERIC_TYPE next(Entry KEY_GENERIC_TYPE entry);
@Override final Entry KEY_GENERIC_TYPE absLowest() {
public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); } Entry KEY_GENERIC_TYPE e = (fromStart ? set.first : (loInclusive ? set.findCeilingNode(lo) : set.findHigherNode(lo)));
return (e == null || tooHigh(e.key)) ? null : e;
@Override
public boolean moveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public boolean moveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public COMPARATOR KEY_GENERIC_TYPE comparator() { return set.comparator(); }
@Override
public abstract BI_ITERATOR KEY_GENERIC_TYPE iterator();
@Override
public KEY_TYPE FIRST_KEY() {
Entry KEY_GENERIC_TYPE entry = findLowest();
return entry == null ? getDefaultMaxValue() : entry.key;
} }
protected Entry KEY_GENERIC_TYPE findLowest() { final Entry KEY_GENERIC_TYPE absHighest() {
if(fromStart) return set.first; Entry KEY_GENERIC_TYPE e = (toEnd ? set.last : (hiInclusive ? set.findFloorNode(hi) : set.findLowerNode(hi)));
Entry KEY_GENERIC_TYPE entry = loInclusive ? set.findCeilingNode(start) : set.findHigherNode(start); return (e == null || tooLow(e.key)) ? null : e;
return entry == null || tooHigh(entry.key) ? null : entry;
} }
@Override final Entry KEY_GENERIC_TYPE absCeiling(KEY_TYPE key) {
public KEY_TYPE POLL_FIRST_KEY() { if (tooLow(key)) return absLowest();
if(fromStart) return set.POLL_FIRST_KEY(); Entry KEY_GENERIC_TYPE e = set.findCeilingNode(key);
Entry KEY_GENERIC_TYPE entry = loInclusive ? set.findCeilingNode(start) : set.findHigherNode(start); return (e == null || tooHigh(e.key)) ? null : e;
if(entry != null && !tooHigh(entry.key)) {
KEY_TYPE value = entry.key;
set.removeNode(entry);
return value;
}
return getDefaultMaxValue();
} }
@Override final Entry KEY_GENERIC_TYPE absHigher(KEY_TYPE key) {
public KEY_TYPE LAST_KEY() { if (tooLow(key)) return absLowest();
Entry KEY_GENERIC_TYPE entry = findHighest(); Entry KEY_GENERIC_TYPE e = set.findHigherNode(key);
return entry == null ? getDefaultMinValue() : entry.key; return (e == null || tooHigh(e.key)) ? null : e;
} }
protected Entry KEY_GENERIC_TYPE findHighest() { final Entry KEY_GENERIC_TYPE absFloor(KEY_TYPE key) {
if(toEnd) return set.last; if (tooHigh(key)) return absHighest();
Entry KEY_GENERIC_TYPE entry = hiInclusive ? set.findFloorNode(end) : set.findLowerNode(end); Entry KEY_GENERIC_TYPE e = set.findFloorNode(key);
return entry == null || tooLow(entry.key) ? null : entry; return (e == null || tooLow(e.key)) ? null : e;
} }
@Override final Entry KEY_GENERIC_TYPE absLower(KEY_TYPE key) {
public KEY_TYPE POLL_LAST_KEY() { if (tooHigh(key)) return absHighest();
if(toEnd) return set.POLL_LAST_KEY(); Entry KEY_GENERIC_TYPE e = set.findLowerNode(key);
Entry KEY_GENERIC_TYPE entry = hiInclusive ? set.findFloorNode(end) : set.findLowerNode(end); return (e == null || tooLow(e.key)) ? null : e;
if(entry != null && !tooLow(entry.key)) {
KEY_TYPE value = entry.key;
set.removeNode(entry);
return value;
}
return getDefaultMinValue();
} }
final Entry KEY_GENERIC_TYPE absHighFence() { return (toEnd ? null : (hiInclusive ? set.findHigherNode(hi) : set.findCeilingNode(hi))); }
final Entry KEY_GENERIC_TYPE absLowFence() { return (fromStart ? null : (loInclusive ? set.findLowerNode(lo) : set.findFloorNode(lo))); }
@Override @Override
public boolean add(KEY_TYPE o) { public boolean add(KEY_TYPE o) {
if(!inRange(o)) throw new IllegalArgumentException("Key is out of range"); if(!inRange(o)) throw new IllegalArgumentException("Key is out of range");
@ -1086,50 +1105,85 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
} }
@Override @Override
public KEY_TYPE lower(KEY_TYPE e) { public boolean isEmpty() {
if(tooHigh(e)) { if(fromStart && toEnd) return set.isEmpty();
Entry KEY_GENERIC_TYPE entry = findHighest(); Entry KEY_GENERIC_TYPE n = absLowest();
return entry == null ? getDefaultMinValue() : entry.key; return n == null || tooHigh(n.key);
}
Entry KEY_GENERIC_TYPE entry = set.findLowerNode(e);
return entry == null || tooHigh(entry.key) ? getDefaultMaxValue() : entry.key;
}
@Override
public KEY_TYPE floor(KEY_TYPE e) {
if(tooHigh(e)) {
Entry KEY_GENERIC_TYPE entry = findHighest();
return entry == null ? getDefaultMinValue() : entry.key;
}
Entry KEY_GENERIC_TYPE entry = set.findFloorNode(e);
return entry == null || tooHigh(entry.key) ? getDefaultMaxValue() : entry.key;
}
@Override
public KEY_TYPE ceiling(KEY_TYPE e) {
if(tooLow(e)) {
Entry KEY_GENERIC_TYPE entry = findLowest();
return entry == null ? getDefaultMaxValue() : entry.key;
}
Entry KEY_GENERIC_TYPE entry = set.findCeilingNode(e);
return entry == null || tooLow(entry.key) ? getDefaultMinValue() : entry.key;
}
@Override
public KEY_TYPE higher(KEY_TYPE e) {
if(tooLow(e)) {
Entry KEY_GENERIC_TYPE entry = findLowest();
return entry == null ? getDefaultMaxValue() : entry.key;
}
Entry KEY_GENERIC_TYPE entry = set.findHigherNode(e);
return entry == null || tooLow(entry.key) ? getDefaultMinValue() : entry.key;
} }
@Override @Override
public int size() { public int size() {
return fromStart && toEnd ? set.size() : iterator().skip(Integer.MAX_VALUE); if(fromStart && toEnd) return set.size();
int i = 0;
for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();iter.NEXT(),i++);
return i;
} }
@Override
public KEY_TYPE lower(KEY_TYPE e) {
return lowKeyOrNull(subLower(e));
}
@Override
public KEY_TYPE floor(KEY_TYPE e) {
return lowKeyOrNull(subFloor(e));
}
@Override
public KEY_TYPE ceiling(KEY_TYPE e) {
return highKeyOrNull(subCeiling(e));
}
@Override
public KEY_TYPE higher(KEY_TYPE e) {
return highKeyOrNull(subHigher(e));
}
@Override
public KEY_TYPE POLL_FIRST_KEY() {
Entry KEY_GENERIC_TYPE entry = subLowest();
if(entry != null) {
KEY_TYPE result = entry.key;
set.removeNode(entry);
return result;
}
return getDefaultMinValue();
}
@Override
public KEY_TYPE POLL_LAST_KEY() {
Entry KEY_GENERIC_TYPE entry = subHighest();
if(entry != null) {
KEY_TYPE result = entry.key;
set.removeNode(entry);
return result;
}
return getDefaultMaxValue();
}
@Override
public KEY_TYPE FIRST_KEY() {
Entry KEY_GENERIC_TYPE entry = subLowest();
if(entry == null) throw new NoSuchElementException();
return entry.key;
}
@Override
public KEY_TYPE LAST_KEY() {
Entry KEY_GENERIC_TYPE entry = subHighest();
if(entry == null) throw new NoSuchElementException();
return entry.key;
}
@Override
public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public boolean moveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override
public boolean moveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
@Override @Override
public SubSet KEY_GENERIC_TYPE copy() { throw new UnsupportedOperationException(); } public SubSet KEY_GENERIC_TYPE copy() { throw new UnsupportedOperationException(); }
@ -1233,16 +1287,124 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
return result; return result;
} }
class SubSetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE class AscendingSubSetIterator implements BI_ITERATOR KEY_GENERIC_TYPE
{ {
Entry KEY_GENERIC_TYPE previous; Entry KEY_GENERIC_TYPE lastReturned;
Entry KEY_GENERIC_TYPE next; Entry KEY_GENERIC_TYPE next;
Entry KEY_GENERIC_TYPE current; boolean unboundForwardFence;
int index = 0; boolean unboundBackwardFence;
KEY_TYPE forwardFence;
KEY_TYPE backwardFence;
public SubSetIterator(Entry KEY_GENERIC_TYPE entry) { public AscendingSubSetIterator(Entry KEY_GENERIC_TYPE first, Entry KEY_GENERIC_TYPE forwardFence, Entry KEY_GENERIC_TYPE backwardFence)
next = entry; {
previous = entry == null ? null : entry.previous(); next = 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;
}
@Override
public boolean hasNext() {
return next != null && (unboundForwardFence || next.key != forwardFence);
}
@Override
public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException();
lastReturned = next;
KEY_TYPE result = next.key;
next = next.next();
return result;
}
@Override
public boolean hasPrevious() {
return next != null && (unboundBackwardFence || next.key != backwardFence);
}
@Override
public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException();
lastReturned = next;
KEY_TYPE result = next.key;
next = next.previous();
return result;
}
@Override
public void remove() {
if(lastReturned == null) throw new IllegalStateException();
if(lastReturned.needsSuccessor()) next = lastReturned;
set.removeNode(lastReturned);
lastReturned = null;
}
}
class DescendingSubSetIterator implements BI_ITERATOR KEY_GENERIC_TYPE
{
Entry KEY_GENERIC_TYPE lastReturned;
Entry KEY_GENERIC_TYPE next;
boolean unboundForwardFence;
boolean unboundBackwardFence;
KEY_TYPE forwardFence;
KEY_TYPE backwardFence;
public DescendingSubSetIterator(Entry KEY_GENERIC_TYPE first, Entry KEY_GENERIC_TYPE forwardFence, Entry KEY_GENERIC_TYPE backwardFence)
{
next = 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;
}
@Override
public boolean hasNext() {
return next != null && (unboundForwardFence || next.key != forwardFence);
}
@Override
public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException();
lastReturned = next;
KEY_TYPE result = next.key;
next = next.previous();
return result;
}
@Override
public boolean hasPrevious() {
return next != null && (unboundBackwardFence || next.key != backwardFence);
}
@Override
public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException();
lastReturned = next;
KEY_TYPE result = next.key;
next = next.next();
return result;
}
@Override
public void remove() {
if(lastReturned == null) throw new IllegalStateException();
set.removeNode(lastReturned);
lastReturned = null;
}
}
}
class AscendingSetIterator implements BI_ITERATOR KEY_GENERIC_TYPE
{
Entry KEY_GENERIC_TYPE lastReturned;
Entry KEY_GENERIC_TYPE next;
public AscendingSetIterator(Entry KEY_GENERIC_TYPE first)
{
next = first;
} }
@Override @Override
@ -1250,91 +1412,46 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
return next != null; return next != null;
} }
@Override
public boolean hasPrevious() {
return previous != null;
}
@Override
public int nextIndex() {
return index;
}
@Override
public int previousIndex() {
return index - 1;
}
boolean topReached(Entry KEY_GENERIC_TYPE entry) {
return hiInclusive ? set.compare(entry.key, end) >= 0 : set.compare(entry.key, end) > 0;
}
boolean bottomReached(Entry KEY_GENERIC_TYPE entry) {
return loInclusive ? set.compare(entry.key, start) <= 0 : set.compare(entry.key, start) < 0;
}
protected void updateNext() {
next = current.next();
if(!toEnd && next != null && topReached(next)) next = null;
}
protected void updatePrevious() {
previous = current.previous();
if(!fromStart && previous != null && bottomReached(previous)) previous = null;
}
@Override @Override
public KEY_TYPE NEXT() { public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException(); if(!hasNext()) throw new NoSuchElementException();
current = previous = next; lastReturned = next;
updateNext(); KEY_TYPE result = next.key;
index++; next = next.next();
return current.key; return result;
}
@Override
public boolean hasPrevious() {
return next != null;
} }
@Override @Override
public KEY_TYPE PREVIOUS() { public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException(); if(!hasPrevious()) throw new NoSuchElementException();
current = next = previous; lastReturned = next;
updatePrevious(); KEY_TYPE result = next.key;
index--; next = next.previous();
return current.key; return result;
} }
@Override @Override
public void remove() { public void remove() {
if(current == null) throw new IllegalStateException(); if(lastReturned == null) throw new IllegalStateException();
if(current == previous) index--; if(lastReturned.needsSuccessor()) next = lastReturned;
updateNext(); removeNode(lastReturned);
updatePrevious(); lastReturned = null;
if(current.needsSuccessor()) next = current;
set.removeNode(current);
current = null;
}
@Override
public void set(KEY_TYPE e){ throw new UnsupportedOperationException(); }
@Override
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
} }
} }
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE class DescendingSetIterator implements BI_ITERATOR KEY_GENERIC_TYPE
{ {
Entry KEY_GENERIC_TYPE previous; Entry KEY_GENERIC_TYPE lastReturned;
Entry KEY_GENERIC_TYPE next; Entry KEY_GENERIC_TYPE next;
Entry KEY_GENERIC_TYPE current;
int index = 0;
public SetIterator(boolean descending) { public DescendingSetIterator(Entry KEY_GENERIC_TYPE first)
if(descending) previous = last; {
else next = first; next = first;
}
public SetIterator(Entry KEY_GENERIC_TYPE entry) {
next = entry;
previous = entry.previous();
} }
@Override @Override
@ -1342,63 +1459,35 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
return next != null; return next != null;
} }
@Override
public boolean hasPrevious() {
return previous != null;
}
@Override
public int nextIndex() {
return index;
}
@Override
public int previousIndex() {
return index - 1;
}
protected void updateNext() {
next = current.next();
}
protected void updatePrevious() {
previous = current.previous();
}
@Override @Override
public KEY_TYPE NEXT() { public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException(); if(!hasNext()) throw new NoSuchElementException();
current = previous = next; lastReturned = next;
updateNext(); KEY_TYPE result = next.key;
index++; next = next.previous();
return current.key; return result;
}
@Override
public boolean hasPrevious() {
return next != null;
} }
@Override @Override
public KEY_TYPE PREVIOUS() { public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException(); if(!hasPrevious()) throw new NoSuchElementException();
current = next = previous; lastReturned = next;
updatePrevious(); KEY_TYPE result = next.key;
index--; next = next.next();
return current.key; return result;
} }
@Override @Override
public void remove() { public void remove() {
if(current == null) throw new IllegalStateException(); if(lastReturned == null) throw new IllegalStateException();
if(current == previous) index--; removeNode(lastReturned);
updateNext(); lastReturned = null;
updatePrevious();
if(current.needsSuccessor()) next = current;
removeNode(current);
current = null;
} }
@Override
public void set(KEY_TYPE e){ throw new UnsupportedOperationException(); }
@Override
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
} }
private static final class Entry KEY_GENERIC_TYPE private static final class Entry KEY_GENERIC_TYPE

View File

@ -1,12 +1,18 @@
package speiger.src.collections.ints.maps; package speiger.src.collections.ints.maps;
import java.util.EnumSet;
import speiger.src.collections.ints.base.BaseInt2IntSortedMapTest; import speiger.src.collections.ints.base.BaseInt2IntSortedMapTest;
import speiger.src.collections.ints.maps.impl.misc.Int2IntArrayMap; import speiger.src.collections.ints.maps.impl.misc.Int2IntArrayMap;
import speiger.src.collections.ints.maps.interfaces.Int2IntSortedMap; import speiger.src.collections.ints.maps.interfaces.Int2IntSortedMap;
import speiger.src.collections.tests.SortedMapTests;
@SuppressWarnings("javadoc") @SuppressWarnings("javadoc")
public class Int2IntArrayMapTest extends BaseInt2IntSortedMapTest public class Int2IntArrayMapTest extends BaseInt2IntSortedMapTest
{ {
@Override
public EnumSet<SortedMapTests> getValidSortedMapTests() { return EnumSet.complementOf(EnumSet.of(SortedMapTests.SUB_MAP, SortedMapTests.HEAD_MAP, SortedMapTests.TAIL_MAP)); }
@Override @Override
public Int2IntSortedMap createMap(int[] keys, int[] values) public Int2IntSortedMap createMap(int[] keys, int[] values)
{ {

View File

@ -1,10 +1,15 @@
package speiger.src.collections.ints.sets; package speiger.src.collections.ints.sets;
import java.util.EnumSet;
import speiger.src.collections.ints.base.BaseIntSortedSetTest; import speiger.src.collections.ints.base.BaseIntSortedSetTest;
import speiger.src.collections.tests.SortedSetTest;
@SuppressWarnings("javadoc") @SuppressWarnings("javadoc")
public class IntArraySetTests extends BaseIntSortedSetTest public class IntArraySetTests extends BaseIntSortedSetTest
{ {
@Override
protected EnumSet<SortedSetTest> getValidSortedSetTests() { return EnumSet.complementOf(EnumSet.of(SortedSetTest.SUB_SET, SortedSetTest.HEAD_SET, SortedSetTest.TAIL_SET)); }
@Override @Override
protected IntSortedSet create(int[] data) { return new IntArraySet(data.clone()); } protected IntSortedSet create(int[] data) { return new IntArraySet(data.clone()); }
} }

View File

@ -2,14 +2,17 @@ package speiger.src.collections.objects.map;
import java.util.Comparator; import java.util.Comparator;
import java.util.Map; import java.util.Map;
import java.util.NavigableMap;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.google.common.collect.testing.AnEnum; import com.google.common.collect.testing.AnEnum;
import com.google.common.collect.testing.MapTestSuiteBuilder; import com.google.common.collect.testing.MapTestSuiteBuilder;
import com.google.common.collect.testing.NavigableMapTestSuiteBuilder;
import com.google.common.collect.testing.TestEnumMapGenerator; import com.google.common.collect.testing.TestEnumMapGenerator;
import com.google.common.collect.testing.TestStringMapGenerator; import com.google.common.collect.testing.TestStringMapGenerator;
import com.google.common.collect.testing.TestStringSortedMapGenerator;
import com.google.common.collect.testing.features.CollectionFeature; import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize; import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.MapFeature; import com.google.common.collect.testing.features.MapFeature;
@ -39,10 +42,10 @@ public class ObjectMapTests extends TestCase
suite.addTest(suite("LinkedHashMap", Object2ObjectLinkedOpenHashMap::new, true)); suite.addTest(suite("LinkedHashMap", Object2ObjectLinkedOpenHashMap::new, true));
suite.addTest(suite("CustomHashMap", () -> new Object2ObjectOpenCustomHashMap<>(Strategy.INSTANCE), true)); suite.addTest(suite("CustomHashMap", () -> new Object2ObjectOpenCustomHashMap<>(Strategy.INSTANCE), true));
suite.addTest(suite("LinkedCustomHashMap", () -> new Object2ObjectLinkedOpenCustomHashMap<>(Strategy.INSTANCE), true)); suite.addTest(suite("LinkedCustomHashMap", () -> new Object2ObjectLinkedOpenCustomHashMap<>(Strategy.INSTANCE), true));
suite.addTest(suite("RBTreeMap_NonNull", Object2ObjectRBTreeMap::new, false)); suite.addTest(navigableSuite("RBTreeMap_NonNull", Object2ObjectRBTreeMap::new, false));
suite.addTest(suite("AVLTreeMap_NonNull", Object2ObjectAVLTreeMap::new, false)); suite.addTest(navigableSuite("AVLTreeMap_NonNull", Object2ObjectAVLTreeMap::new, false));
suite.addTest(suite("RBTreeMap_Null", () -> new Object2ObjectRBTreeMap<String, String>(Comparator.nullsFirst(Comparator.naturalOrder())), true)); suite.addTest(navigableSuite("RBTreeMap_Null", () -> new Object2ObjectRBTreeMap<>(new NullFriendlyComparator()), true));
suite.addTest(suite("AVLTreeMap_Null", () -> new Object2ObjectAVLTreeMap<String, String>(Comparator.nullsFirst(Comparator.naturalOrder())), true)); suite.addTest(navigableSuite("AVLTreeMap_Null", () -> new Object2ObjectAVLTreeMap<>(new NullFriendlyComparator()), true));
suite.addTest(immutableSuit("ImmutableMap", ImmutableObject2ObjectOpenHashMap::new)); suite.addTest(immutableSuit("ImmutableMap", ImmutableObject2ObjectOpenHashMap::new));
suite.addTest(suite("ArrayMap", Object2ObjectArrayMap::new, true)); suite.addTest(suite("ArrayMap", Object2ObjectArrayMap::new, true));
suite.addTest(enumSuite("EnumMap", () -> new Enum2ObjectMap<>(AnEnum.class))); suite.addTest(enumSuite("EnumMap", () -> new Enum2ObjectMap<>(AnEnum.class)));
@ -66,6 +69,22 @@ public class ObjectMapTests extends TestCase
return builder.createTestSuite(); return builder.createTestSuite();
} }
public static Test navigableSuite(String name, Supplier<NavigableMap<String, String>> factory, boolean allowNull)
{
MapTestSuiteBuilder<String, String> builder = NavigableMapTestSuiteBuilder.using(new TestStringSortedMapGenerator() {
@Override
protected NavigableMap<String, String> create(Map.Entry<String, String>[] entries) {
NavigableMap<String, String> map = factory.get();
for(Map.Entry<String, String> entry : entries) {
map.put(entry.getKey(), entry.getValue());
}
return map;
}
}).named(name).withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE, MapFeature.ALLOWS_NULL_VALUES, CollectionFeature.SUPPORTS_ITERATOR_REMOVE);
if(allowNull) builder.withFeatures(MapFeature.ALLOWS_NULL_KEYS, MapFeature.ALLOWS_ANY_NULL_QUERIES);
return builder.createTestSuite();
}
public static Test immutableSuit(String name, BiFunction<String[], String[], Map<String, String>> factory) { public static Test immutableSuit(String name, BiFunction<String[], String[], Map<String, String>> factory) {
MapTestSuiteBuilder<String, String> builder = MapTestSuiteBuilder.using(new TestStringMapGenerator() { MapTestSuiteBuilder<String, String> builder = MapTestSuiteBuilder.using(new TestStringMapGenerator() {
@Override @Override
@ -97,6 +116,14 @@ public class ObjectMapTests extends TestCase
return builder.createTestSuite(); return builder.createTestSuite();
} }
private static final class NullFriendlyComparator implements Comparator<String>
{
@Override
public int compare(String left, String right) {
return String.valueOf(left).compareTo(String.valueOf(right));
}
}
private static class Strategy implements ObjectStrategy<String> private static class Strategy implements ObjectStrategy<String>
{ {
static final Strategy INSTANCE = new Strategy(); static final Strategy INSTANCE = new Strategy();

View File

@ -1,12 +1,15 @@
package speiger.src.collections.objects.set; package speiger.src.collections.objects.set;
import java.util.Comparator; import java.util.Comparator;
import java.util.NavigableSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import com.google.common.collect.testing.NavigableSetTestSuiteBuilder;
import com.google.common.collect.testing.SetTestSuiteBuilder; import com.google.common.collect.testing.SetTestSuiteBuilder;
import com.google.common.collect.testing.TestStringSetGenerator; import com.google.common.collect.testing.TestStringSetGenerator;
import com.google.common.collect.testing.TestStringSortedSetGenerator;
import com.google.common.collect.testing.features.CollectionFeature; import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize; import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.SetFeature; import com.google.common.collect.testing.features.SetFeature;
@ -36,15 +39,14 @@ public class ObjectSetTests extends TestCase
suite.addTest(suite("LinkedCustomHashSet", T -> new ObjectLinkedOpenCustomHashSet<>(T, Strategy.INSTANCE), true)); suite.addTest(suite("LinkedCustomHashSet", T -> new ObjectLinkedOpenCustomHashSet<>(T, Strategy.INSTANCE), true));
suite.addTest(immutableSuite("ImmutableHashSet", ImmutableObjectOpenHashSet::new)); suite.addTest(immutableSuite("ImmutableHashSet", ImmutableObjectOpenHashSet::new));
suite.addTest(suite("ArraySet", ObjectArraySet::new, true)); suite.addTest(suite("ArraySet", ObjectArraySet::new, true));
suite.addTest(suite("RBTreeSet_NonNull", ObjectRBTreeSet::new, false)); suite.addTest(navigableSuite("RBTreeSet_NonNull", ObjectRBTreeSet::new, false));
suite.addTest(suite("AVLTreeSet_NonNull", ObjectAVLTreeSet::new, false)); suite.addTest(navigableSuite("AVLTreeSet_NonNull", ObjectAVLTreeSet::new, false));
suite.addTest(suite("RBTreeSet_Null", T -> new ObjectRBTreeSet<>(T, Comparator.nullsFirst(Comparator.naturalOrder())), true)); suite.addTest(navigableSuite("RBTreeSet_Null", T -> new ObjectRBTreeSet<>(T, Comparator.nullsFirst(Comparator.naturalOrder())), true));
suite.addTest(suite("AVLTreeSet_Null", T -> new ObjectAVLTreeSet<>(T, Comparator.nullsFirst(Comparator.naturalOrder())), true)); suite.addTest(navigableSuite("AVLTreeSet_Null", T -> new ObjectAVLTreeSet<>(T, Comparator.nullsFirst(Comparator.naturalOrder())), true));
return suite; return suite;
} }
public static Test suite(String name, Function<String[], Set<String>> factory, boolean allowNull) public static Test suite(String name, Function<String[], Set<String>> factory, boolean allowNull) {
{
SetTestSuiteBuilder<String> generator = SetTestSuiteBuilder.using(new TestStringSetGenerator() { SetTestSuiteBuilder<String> generator = SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override @Override
protected Set<String> create(String[] elements) { return factory.apply(elements); } protected Set<String> create(String[] elements) { return factory.apply(elements); }
@ -53,17 +55,23 @@ public class ObjectSetTests extends TestCase
return generator.createTestSuite(); return generator.createTestSuite();
} }
public static Test navigableSuite(String name, Function<String[], NavigableSet<String>> factory, boolean allowNull) {
SetTestSuiteBuilder<String> generator = NavigableSetTestSuiteBuilder.using(new TestStringSortedSetGenerator() {
@Override
protected NavigableSet<String> create(String[] elements) { return factory.apply(elements); }
}).named(name).withFeatures(CollectionSize.ANY, SetFeature.GENERAL_PURPOSE);
if(allowNull) generator.withFeatures(CollectionFeature.ALLOWS_NULL_VALUES);
return generator.createTestSuite();
}
public static Test immutableSuite(String name, Function<String[], Set<String>> factory) public static Test immutableSuite(String name, Function<String[], Set<String>> factory) {
{
return SetTestSuiteBuilder.using(new TestStringSetGenerator() { return SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override @Override
protected Set<String> create(String[] elements) { return factory.apply(elements); } protected Set<String> create(String[] elements) { return factory.apply(elements); }
}).named(name).withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES).createTestSuite(); }).named(name).withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES).createTestSuite();
} }
private static class Strategy implements ObjectStrategy<String> private static class Strategy implements ObjectStrategy<String> {
{
static final Strategy INSTANCE = new Strategy(); static final Strategy INSTANCE = new Strategy();
@Override @Override
@ -75,6 +83,5 @@ public class ObjectSetTests extends TestCase
public boolean equals(String key, String value) { public boolean equals(String key, String value) {
return Objects.equals(key, value); return Objects.equals(key, value);
} }
} }
} }