Next big batch of features.

-Added: Tests for IntSortedSet, IntNavigableSet.
-Added: Test Classes for: Open/Custom/Linked HashSet, TreeSets, ArraySet
-Changed: MemFreeMergeSort got improved by a lot.
-Fixed: Bugs that the tests uncovered.
-Note: TreeSets still have issues. But every other collection type is fixed.
This commit is contained in:
Speiger committed 2021-01-08 21:12:20 +01:00
1 parent 0123cb8937
commit c0c719f2b6
23 files changed
+765 -265

No files matched your search

@@ -1,14 +1,22 @@
package speiger.src.collections.PACKAGE.sets;
import java.util.NoSuchElementException;
import java.util.Collection;
#if TYPE_OBJECT
import java.util.Comparator;
#endif
import java.util.Iterator;
import java.util.NoSuchElementException;
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
#endif
import speiger.src.collections.PACKAGE.collections.COLLECTION;
import speiger.src.collections.PACKAGE.collections.ITERATOR;
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.utils.ITERATORS;
#endif
import speiger.src.collections.utils.SanityChecks;
public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE
{
@@ -30,6 +38,36 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
public AVL_TREE_SET() {
}
public AVL_TREE_SET(KEY_TYPE[] array) {
this(array, 0, array.length);
}
public AVL_TREE_SET(KEY_TYPE[] array, int offset, int length) {
SanityChecks.checkArrayCapacity(array.length, offset, length);
for(int i = 0;i<length;i++) add(array[offset+i]);
}
@Deprecated
public AVL_TREE_SET(Collection<? extends CLASS_TYPE> collection) {
addAll(collection);
}
public AVL_TREE_SET(COLLECTION KEY_GENERIC_TYPE collection) {
addAll(collection);
}
public AVL_TREE_SET(Iterator<CLASS_TYPE> iterator) {
#if !TYPE_OBJECT
this(ITERATORS.wrap(iterator));
#else
while(iterator.hasNext()) add(iterator.next());
#endif
}
public AVL_TREE_SET(ITERATOR KEY_GENERIC_TYPE iterator) {
while(iterator.hasNext()) add(iterator.NEXT());
}
#if !TYPE_OBJECT
@Override
public void setDefaultMaxValue(KEY_TYPE value) { defaultMaxNotFound = value; }
@@ -31,11 +31,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
}
public ARRAY_SET(int capacity) {
#if TYPE_OBJECT
data = (KEY_TYPE[])new Object[capacity];
#else
data = new KEY_TYPE[capacity];
#endif
data = NEW_KEY_ARRAY(capacity);
}
public ARRAY_SET(KEY_TYPE[] array) {
@@ -43,7 +39,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
}
public ARRAY_SET(KEY_TYPE[] array, int length) {
data = array;
data = Arrays.copyOf(array, length);
size = length;
}
@@ -94,7 +90,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
else if(index != 0) {
o = data[index];
System.arraycopy(data, 0, data, 1, index);
data[index] = o;
data[0] = o;
}
return false;
}
@@ -110,7 +106,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
else if(index != size - 1) {
o = data[index];
System.arraycopy(data, index+1, data, index, size - index);
data[size] = o;
data[size-1] = o;
}
return false;
}
@@ -121,7 +117,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
if(index > 0) {
o = data[index];
System.arraycopy(data, 0, data, 1, index);
data[index] = o;
data[0] = o;
return true;
}
return false;
@@ -132,8 +128,8 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
int index = findIndex(o);
if(index != -1 && index != size - 1) {
o = data[index];
System.arraycopy(data, index+1, data, index, size - index);
data[size] = o;
System.arraycopy(data, index+1, data, index, size - index - 1);
data[size-1] = o;
return true;
}
return false;
@@ -169,7 +165,11 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
public boolean remove(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1) {
System.arraycopy(data, index+1, data, index, size - index);
size--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
#if TYPE_OBJECT
data[size] = EMPTY_VALUE;
#endif
return true;
}
return false;
@@ -180,8 +180,11 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
public boolean remove(Object o) {
int index = findIndex(o);
if(index != -1) {
System.arraycopy(data, index+1, data, index, size - index);
data[size-1] = EMPTY_VALUE;
size--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
#if TYPE_OBJECT
data[size] = EMPTY_VALUE;
#endif
return true;
}
return false;
@@ -192,7 +195,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
public KEY_TYPE POLL_FIRST_KEY() {
if(size == 0) throw new NoSuchElementException();
KEY_TYPE result = data[0];
System.arraycopy(data, 1, data, 0, size);
System.arraycopy(data, 1, data, 0, size - 1);
#if TYPE_OBJECT
data[size-1] = EMPTY_VALUE;
#endif
@@ -202,12 +205,13 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public KEY_TYPE POLL_LAST_KEY() {
if(size == 0) throw new NoSuchElementException();
size--;
#if TYPE_OBJECT
KEY_TYPE result = data[size-1];
data[size-1] = EMPTY_VALUE;
KEY_TYPE result = data[size];
data[size] = EMPTY_VALUE;
return result;
#else
return data[--size];
return data[size];
#endif
}
@@ -242,14 +246,14 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
int fromIndex = findIndex(fromElement);
int toIndex = findIndex(toElement);
if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException();
return new SubSet(fromIndex, toIndex - fromIndex);
return new SubSet(fromIndex, toIndex - fromIndex + 1);
}
@Override
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) {
int toIndex = findIndex(toElement);
if(toIndex == -1) throw new NoSuchElementException();
return new SubSet(0, toIndex);
return new SubSet(0, toIndex+1);
}
@Override
@@ -282,14 +286,16 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
this.offset = offset;
this.length = length;
}
int end() { return offset+length; }
@Override
public boolean add(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1) {
if(index == -1) {
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
System.arraycopy(data, (offset+length), data, (offset+length)+1, size-(offset+length));
data[offset+length] = o;
if(end() != size) System.arraycopy(data, end(), data, end()+1, size-(offset+length));
data[end()] = o;
size++;
length++;
return true;
@@ -321,8 +327,8 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
int index = findIndex(o);
if(index == -1) {
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
System.arraycopy(data, (offset+length)+1, data, (offset+length), size-(offset+length));
data[offset+length] = o;
System.arraycopy(data, end()+1, data, end(), size-end());
data[end()] = o;
size++;
length++;
return true;
@@ -338,7 +344,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public boolean moveToFirst(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1 && index != offset) {
if(index > offset) {
o = data[index];
System.arraycopy(data, offset, data, offset+1, index-offset);
data[offset] = o;
@@ -350,10 +356,10 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public boolean moveToLast(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1 && index != (offset+length) - 1) {
if(index != -1 && index < end()-1) {
o = data[index];
System.arraycopy(data, offset+1, data, offset, index-offset);
data[offset+length] = o;
System.arraycopy(data, index+1, data, index, end()-index-1);
data[end()-1] = o;
return true;
}
return false;
@@ -380,7 +386,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public KEY_TYPE LAST_KEY() {
if(length == 0) throw new NoSuchElementException();
return data[(offset + length) - 1];
return data[end()-1];
}
#if !TYPE_OBJECT
@@ -388,9 +394,9 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
public boolean remove(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1) {
System.arraycopy(data, index+1, data, index, size - index);
size--;
length--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
return true;
}
return false;
@@ -401,10 +407,12 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
public boolean remove(Object o) {
int index = findIndex(o);
if(index != -1) {
System.arraycopy(data, index+1, data, index, size - index);
data[size-1] = EMPTY_VALUE;
size--;
length--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
#if TYPE_OBJECT
data[size] = EMPTY_VALUE;
#endif
return true;
}
return false;
@@ -413,13 +421,13 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public KEY_TYPE POLL_FIRST_KEY() {
if(length == 0) throw new NoSuchElementException();
size--;
length--;
KEY_TYPE result = data[offset];
System.arraycopy(data, offset+1, data, offset, size-offset);
#if TYPE_OBJECT
data[size-1] = EMPTY_VALUE;
data[size] = EMPTY_VALUE;
#endif
size--;
length--;
return result;
}
@@ -427,12 +435,12 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
public KEY_TYPE POLL_LAST_KEY() {
if(length == 0) throw new NoSuchElementException();
KEY_TYPE result = data[offset+length];
System.arraycopy(data, (offset+length)+1, data, (offset+length), size-(offset+length));
#if TYPE_OBJECT
data[size-1] = EMPTY_VALUE;
#endif
size--;
length--;
System.arraycopy(data, end()+1, data, end(), size-end());
#if TYPE_OBJECT
data[size] = EMPTY_VALUE;
#endif
return result;
}
@@ -482,17 +490,99 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
#if !TYPE_OBJECT
protected int findIndex(KEY_TYPE o) {
for(int i = size-1;i>=0;i--)
for(int i = length-1;i>=0;i--)
if(EQUALS(data[offset+i], o)) return i + offset;
return -1;
}
#endif
protected int findIndex(Object o) {
for(int i = size-1;i>=0;i--)
for(int i = length-1;i>=0;i--)
if(EQUALS_KEY_TYPE(data[offset+i], o)) return i + offset;
return -1;
}
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
int index;
int lastReturned = -1;
public SetIterator(int index) {
this.index = index;
}
@Override
public boolean hasNext() {
return index < size();
}
@Override
public KEY_TYPE NEXT() {
lastReturned = index;
return data[index++];
}
@Override
public boolean hasPrevious() {
return index > 0;
}
@Override
public KEY_TYPE PREVIOUS() {
lastReturned = index;
return data[index--];
}
@Override
public int nextIndex() {
return index;
}
@Override
public int previousIndex() {
return index-1;
}
@Override
public void remove() {
if(lastReturned == -1)
throw new IllegalStateException();
SubSet.this.remove(data[lastReturned]);
if(lastReturned < index)
index--;
lastReturned = -1;
}
#if TYPE_OBJECT
@Override
public void set(Object e) { throw new UnsupportedOperationException(); }
@Override
public void add(Object e) { throw new UnsupportedOperationException(); }
#else
@Override
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
@Override
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
#endif
@Override
public int skip(int amount) {
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
int steps = Math.min(amount, (size() - 1) - index);
index += steps;
return steps;
}
@Override
public int back(int amount) {
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
int steps = Math.min(amount, index);
index -= steps;
return steps;
}
}
}
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
@@ -158,6 +158,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
@Override
public boolean moveToFirst(KEY_TYPE o) {
if(strategy.equals(FIRST_KEY(), o)) return false;
if(strategy.equals(o, EMPTY_VALUE)) {
if(containsNull) {
moveToFirstIndex(nullIndex);
@@ -180,6 +181,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
@Override
public boolean moveToLast(KEY_TYPE o) {
if(strategy.equals(LAST_KEY(), o)) return false;
if(strategy.equals(o, EMPTY_VALUE)) {
if(containsNull) {
moveToLastIndex(nullIndex);
@@ -290,14 +292,14 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
}
else {
links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | (-1 & 0xFFFFFFFFL);
links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
lastIndex = pos;
}
}
@Override
protected void onNodeRemoved(int pos) {
if(size == 0) firstIndex = lastIndex = 0;
if(size == 0) firstIndex = lastIndex = -1;
else if(firstIndex == pos) {
firstIndex = (int)links[pos];
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
@@ -344,11 +346,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
@Override
protected void rehash(int newSize) {
int newMask = newSize - 1;
#if TYPE_OBJECT
KEY_TYPE[] newKeys = (KEY_TYPE[])new Object[newSize + 1];
#else
KEY_TYPE[] newKeys = new KEY_TYPE[newSize + 1];
#endif
KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
long[] newLinks = new long[newSize + 1];
int newPrev = -1;
for(int j = size, i = firstIndex, pos = 0, prev = -1;j != 0;) {
@@ -471,7 +469,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
ensureIndexKnown();
if(current == previous) {
index--;
previous = (int)(links[current] >> 32);
previous = (int)(links[current] >>> 32);
}
else next = (int)links[current];
size--;
@@ -490,7 +488,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
current = -1;
KEY_TYPE current;
while(true) {
last = ((last = startPos) + 1) & mask;
startPos = ((last = startPos) + 1) & mask;
while(true){
if(strategy.equals((current = keys[startPos]), EMPTY_VALUE)) {
keys[last] = EMPTY_VALUE;
@@ -520,7 +518,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
@Override
public KEY_TYPE NEXT() {
if(!hasPrevious()) throw new NoSuchElementException();
if(!hasNext()) throw new NoSuchElementException();
current = next;
next = (int)(links[current]);
previous = current;
@@ -160,6 +160,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
@Override
public boolean moveToFirst(KEY_TYPE o) {
if(EQUALS(FIRST_KEY(), o)) return false;
if(EQUALS_NULL(o)) {
if(containsNull) {
moveToFirstIndex(nullIndex);
@@ -182,6 +183,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
@Override
public boolean moveToLast(KEY_TYPE o) {
if(EQUALS(LAST_KEY(), o)) return false;
if(EQUALS_NULL(o)) {
if(containsNull) {
moveToLastIndex(nullIndex);
@@ -292,14 +294,14 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
}
else {
links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | (-1 & 0xFFFFFFFFL);
links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
lastIndex = pos;
}
}
@Override
protected void onNodeRemoved(int pos) {
if(size == 0) firstIndex = lastIndex = 0;
if(size == 0) firstIndex = lastIndex = -1;
else if(firstIndex == pos) {
firstIndex = (int)links[pos];
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
@@ -346,11 +348,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
@Override
protected void rehash(int newSize) {
int newMask = newSize - 1;
#if TYPE_OBJECT
KEY_TYPE[] newKeys = (KEY_TYPE[])new Object[newSize + 1];
#else
KEY_TYPE[] newKeys = new KEY_TYPE[newSize + 1];
#endif
KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
long[] newLinks = new long[newSize + 1];
int newPrev = -1;
for(int j = size, i = firstIndex, pos = 0, prev = -1;j != 0;) {
@@ -473,7 +471,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
ensureIndexKnown();
if(current == previous) {
index--;
previous = (int)(links[current] >> 32);
previous = (int)(links[current] >>> 32);
}
else next = (int)links[current];
size--;
@@ -492,7 +490,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
current = -1;
KEY_TYPE current;
while(true) {
last = ((last = startPos) + 1) & mask;
startPos = ((last = startPos) + 1) & mask;
while(true){
if(EQUALS_NULL((current = keys[startPos]))) {
keys[last] = EMPTY_VALUE;
@@ -522,7 +520,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
@Override
public KEY_TYPE NEXT() {
if(!hasPrevious()) throw new NoSuchElementException();
if(!hasNext()) throw new NoSuchElementException();
current = next;
next = (int)(links[current]);
previous = current;
@@ -46,11 +46,7 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
this.minCapacity = nullIndex = HashUtil.arraySize(minCapacity, loadFactor);
mask = nullIndex - 1;
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
#if TYPE_OBJECT
keys = (KEY_TYPE[])new Object[nullIndex + 1];
#else
keys = new KEY_TYPE[nullIndex + 1];
#endif
keys = NEW_KEY_ARRAY(nullIndex + 1);
this.strategy = strategy;
}
@@ -132,7 +128,7 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
KEY_TYPE current = keys[pos];
if(!strategy.equals(current, EMPTY_VALUE)) {
if(strategy.equals(current, o)) return false;
while(!strategy.equals((current = keys[++pos & mask]), EMPTY_VALUE))
while(!strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_VALUE))
if(strategy.equals(current, o)) return false;
}
keys[pos] = o;
@@ -163,10 +159,10 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
if(strategy.equals((KEY_TYPE)o, EMPTY_VALUE)) return containsNull;
int pos = HashUtil.mix(strategy.hashCode((KEY_TYPE)o)) & mask;
KEY_TYPE current = keys[pos];
if(!strategy.equals(current, EMPTY_VALUE)) return false;
if(strategy.equals(current, EMPTY_VALUE)) return false;
if(strategy.equals(current, (KEY_TYPE)o)) return true;
while(true) {
if(strategy.equals((current = keys[++pos & mask]), EMPTY_VALUE)) return false;
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_VALUE)) return false;
else if(strategy.equals(current, (KEY_TYPE)o)) return true;
}
}
@@ -176,10 +172,10 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
if(strategy.equals((KEY_TYPE)o, EMPTY_VALUE)) return (containsNull ? removeNullIndex() : false);
int pos = HashUtil.mix(strategy.hashCode((KEY_TYPE)o)) & mask;
KEY_TYPE current = keys[pos];
if(!strategy.equals(current, EMPTY_VALUE)) return false;
if(strategy.equals(current, EMPTY_VALUE)) return false;
if(strategy.equals(current, (KEY_TYPE)o)) return removeIndex(pos);
while(true) {
if(strategy.equals((current = keys[++pos & mask]), EMPTY_VALUE)) return false;
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_VALUE)) return false;
else if(strategy.equals(current, (KEY_TYPE)o)) return removeIndex(pos);
}
}
@@ -190,10 +186,10 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
if(strategy.equals(o, EMPTY_VALUE)) return containsNull;
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
KEY_TYPE current = keys[pos];
if(!strategy.equals(current, EMPTY_VALUE)) return false;
if(strategy.equals(current, EMPTY_VALUE)) return false;
if(strategy.equals(current, o)) return true;
while(true) {
if(strategy.equals((current = keys[++pos & mask]), EMPTY_VALUE)) return false;
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_VALUE)) return false;
else if(strategy.equals(current, o)) return true;
}
}
@@ -203,10 +199,10 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
if(strategy.equals(o, EMPTY_VALUE)) return (containsNull ? removeNullIndex() : false);
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
KEY_TYPE current = keys[pos];
if(!strategy.equals(current, EMPTY_VALUE)) return false;
if(strategy.equals(current, EMPTY_VALUE)) return false;
if(strategy.equals(current, o)) return removeIndex(pos);
while(true) {
if(strategy.equals((current = keys[++pos & mask]), EMPTY_VALUE)) return false;
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_VALUE)) return false;
else if(strategy.equals(current, o)) return removeIndex(pos);
}
}
@@ -278,15 +274,11 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
protected void rehash(int newSize) {
int newMask = newSize - 1;
#if TYPE_OBJECT
KEY_TYPE[] newKeys = (KEY_TYPE[])new Object[newSize + 1];
#else
KEY_TYPE[] newKeys = new KEY_TYPE[newSize + 1];
#endif
KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
for(int i = nullIndex, pos = 0, j = (size - (containsNull ? 1 : 0));j-- != 0;) {
while(strategy.equals(keys[--i], EMPTY_VALUE));
if(!strategy.equals(newKeys[pos = HashUtil.mix(TO_HASH(keys[i])) & newMask], EMPTY_VALUE))
while(!strategy.equals(newKeys[++pos & newMask], EMPTY_VALUE));
while(!strategy.equals(newKeys[pos = (++pos & newMask)], EMPTY_VALUE));
newKeys[pos] = keys[i];
}
nullIndex = newSize;
@@ -316,31 +308,46 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
private class SetIterator implements ITERATOR KEY_GENERIC_TYPE {
int pos = nullIndex;
int lastReturned = -1;
int count = size;
int nextIndex = Integer.MIN_VALUE;
boolean returnNull = containsNull;
LIST KEY_GENERIC_TYPE wrapped = null;
@Override
public boolean hasNext() {
return count != 0;
if(nextIndex == Integer.MIN_VALUE) {
if(returnNull) {
returnNull = false;
nextIndex = nullIndex;
}
else {
while(true) {
if(--pos < 0) {
if(wrapped == null || wrapped.size() <= -pos - 1) break;
nextIndex = -pos - 1;
break;
}
if(EQUALS_NOT_NULL(keys[pos])){
nextIndex = pos;
break;
}
}
}
}
return nextIndex != Integer.MIN_VALUE;
}
@Override
public KEY_TYPE NEXT() {
if(count != 0) throw new NoSuchElementException();
count--;
if(returnNull) {
returnNull = false;
lastReturned = nullIndex;
return keys[nullIndex];
}
while(true) {
if(pos-- < 0) {
lastReturned = Integer.MAX_VALUE;
return wrapped.GET_KEY(-pos - 1);
}
if(!strategy.equals(keys[pos], EMPTY_VALUE)) return keys[lastReturned = pos];
if(!hasNext()) throw new NoSuchElementException();
if(nextIndex < 0){
lastReturned = Integer.MAX_VALUE;
KEY_TYPE value = wrapped.GET_KEY(nextIndex);
nextIndex = Integer.MIN_VALUE;
return value;
}
KEY_TYPE value = keys[(lastReturned = nextIndex)];
nextIndex = Integer.MIN_VALUE;
return value;
}
@Override
@@ -375,7 +382,7 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
}
if(startPos < last) {
if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
wrapped.add(keys[pos]);
wrapped.add(keys[startPos]);
}
keys[last] = current;
}
@@ -44,11 +44,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
this.minCapacity = nullIndex = HashUtil.arraySize(minCapacity, loadFactor);
mask = nullIndex - 1;
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
#if TYPE_OBJECT
keys = (KEY_TYPE[])new Object[nullIndex + 1];
#else
keys = new KEY_TYPE[nullIndex + 1];
#endif
keys = NEW_KEY_ARRAY(nullIndex + 1);
}
public HASH_SET(KEY_TYPE[] array) {
@@ -125,7 +121,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
KEY_TYPE current = keys[pos];
if(EQUALS_NOT_NULL(current)) {
if(EQUALS(current, o)) return false;
while(EQUALS_NOT_NULL((current = keys[++pos & mask])))
while(EQUALS_NOT_NULL((current = keys[pos = (++pos & mask)])))
if(EQUALS(current, o)) return false;
}
keys[pos] = o;
@@ -158,7 +154,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
if(EQUALS_NULL(current)) return false;
if(EQUALS_KEY_TYPE(current, o)) return true;
while(true) {
if(EQUALS_NULL((current = keys[++pos & mask]))) return false;
if(EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
else if(EQUALS_KEY_TYPE(current, o)) return true;
}
}
@@ -171,7 +167,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
if(EQUALS_NULL(current)) return false;
if(EQUALS_KEY_TYPE(current, o)) return removeIndex(pos);
while(true) {
if(EQUALS_NULL((current = keys[++pos & mask]))) return false;
if(EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
else if(EQUALS_KEY_TYPE(current, o)) return removeIndex(pos);
}
}
@@ -185,7 +181,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
if(EQUALS_NULL(current)) return false;
if(EQUALS(current, o)) return true;
while(true) {
if(EQUALS_NULL((current = keys[++pos & mask]))) return false;
if(EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
else if(EQUALS(current, o)) return true;
}
}
@@ -198,7 +194,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
if(EQUALS_NULL(current)) return false;
if(EQUALS(current, o)) return removeIndex(pos);
while(true) {
if(EQUALS_NULL((current = keys[++pos & mask]))) return false;
if(EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
else if(EQUALS(current, o)) return removeIndex(pos);
}
}
@@ -270,15 +266,11 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
protected void rehash(int newSize) {
int newMask = newSize - 1;
#if TYPE_OBJECT
KEY_TYPE[] newKeys = (KEY_TYPE[])new Object[newSize + 1];
#else
KEY_TYPE[] newKeys = new KEY_TYPE[newSize + 1];
#endif
KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
for(int i = nullIndex, pos = 0, j = (size - (containsNull ? 1 : 0));j-- != 0;) {
while(EQUALS_NULL(keys[--i]));
if(EQUALS_NOT_NULL(newKeys[pos = HashUtil.mix(TO_HASH(keys[i])) & newMask]))
while(EQUALS_NOT_NULL(newKeys[++pos & newMask]));
while(EQUALS_NOT_NULL(newKeys[pos = (++pos & newMask)]));
newKeys[pos] = keys[i];
}
nullIndex = newSize;
@@ -308,31 +300,47 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
private class SetIterator implements ITERATOR KEY_GENERIC_TYPE {
int pos = nullIndex;
int lastReturned = -1;
int count = size;
int nextIndex = Integer.MIN_VALUE;
boolean returnNull = containsNull;
LIST KEY_GENERIC_TYPE wrapped = null;
@Override
public boolean hasNext() {
return count != 0;
if(nextIndex == Integer.MIN_VALUE) {
if(returnNull) {
returnNull = false;
nextIndex = nullIndex;
}
else
{
while(true) {
if(--pos < 0) {
if(wrapped == null || wrapped.size() <= -pos - 1) break;
nextIndex = -pos - 1;
break;
}
if(EQUALS_NOT_NULL(keys[pos])){
nextIndex = pos;
break;
}
}
}
}
return nextIndex != Integer.MIN_VALUE;
}
@Override
public KEY_TYPE NEXT() {
if(count != 0) throw new NoSuchElementException();
count--;
if(returnNull) {
returnNull = false;
lastReturned = nullIndex;
return keys[nullIndex];
}
while(true) {
if(pos-- < 0) {
lastReturned = Integer.MAX_VALUE;
return wrapped.GET_KEY(-pos - 1);
}
if(EQUALS_NOT_NULL(keys[pos])) return keys[lastReturned = pos];
if(!hasNext()) throw new NoSuchElementException();
if(nextIndex < 0){
lastReturned = Integer.MAX_VALUE;
KEY_TYPE value = wrapped.GET_KEY(nextIndex);
nextIndex = Integer.MIN_VALUE;
return value;
}
KEY_TYPE value = keys[(lastReturned = nextIndex)];
nextIndex = Integer.MIN_VALUE;
return value;
}
@Override
@@ -367,7 +375,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
}
if(startPos < last) {
if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
wrapped.add(keys[pos]);
wrapped.add(keys[startPos]);
}
keys[last] = current;
}
@@ -1,14 +1,22 @@
package speiger.src.collections.PACKAGE.sets;
import java.util.NoSuchElementException;
import java.util.Collection;
#if TYPE_OBJECT
import java.util.Comparator;
#endif
import java.util.Iterator;
import java.util.NoSuchElementException;
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
#endif
import speiger.src.collections.PACKAGE.collections.COLLECTION;
import speiger.src.collections.PACKAGE.collections.ITERATOR;
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.utils.ITERATORS;
#endif
import speiger.src.collections.utils.SanityChecks;
public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE
{
@@ -30,6 +38,36 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
public RB_TREE_SET() {
}
public RB_TREE_SET(KEY_TYPE[] array) {
this(array, 0, array.length);
}
public RB_TREE_SET(KEY_TYPE[] array, int offset, int length) {
SanityChecks.checkArrayCapacity(array.length, offset, length);
for(int i = 0;i<length;i++) add(array[offset+i]);
}
@Deprecated
public RB_TREE_SET(Collection<? extends CLASS_TYPE> collection) {
addAll(collection);
}
public RB_TREE_SET(COLLECTION KEY_GENERIC_TYPE collection) {
addAll(collection);
}
public RB_TREE_SET(Iterator<CLASS_TYPE> iterator) {
#if !TYPE_OBJECT
this(ITERATORS.wrap(iterator));
#else
while(iterator.hasNext()) add(iterator.next());
#endif
}
public RB_TREE_SET(ITERATOR KEY_GENERIC_TYPE iterator) {
while(iterator.hasNext()) add(iterator.NEXT());
}
#if !TYPE_OBJECT
@Override
public void setDefaultMaxValue(KEY_TYPE value) { defaultMaxNotFound = value; }