forked from Speiger/Primitive-Collections
New Works.
-Added: Set -Added: Sorted Set -Added: HashSet -Added: LinkedHashSet -Changed: HASH method was changed to TO_HASH -Added: New Patterns.
This commit is contained in:
parent
fc7bca3500
commit
16efec5ca4
|
@ -79,14 +79,30 @@ public enum ClassType
|
|||
return this == BYTE || this == SHORT || this == CHAR || this == FLOAT;
|
||||
}
|
||||
|
||||
public String getEquals()
|
||||
public boolean needsCast()
|
||||
{
|
||||
return this == BYTE || this == SHORT || this == CHAR;
|
||||
}
|
||||
|
||||
public String getComparableValue()
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case DOUBLE: return "Double.doubleToLongBits(%1$s) == Double.doubleToLongBits(%2$s)";
|
||||
case FLOAT: return "Float.floatToIntBits(%1$s) == Float.floatToIntBits(%2$s)";
|
||||
case OBJECT: return "Objects.equals(%1$s, %2$s)";
|
||||
default: return "%1$s == %2$s";
|
||||
case DOUBLE: return "Double.doubleToLongBits(%1$s)";
|
||||
case FLOAT: return "Float.floatToIntBits(%1$s)";
|
||||
case OBJECT: return "%1$s";
|
||||
default: return "%1$s";
|
||||
}
|
||||
}
|
||||
|
||||
public String getEquals(boolean not)
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case DOUBLE: return "Double.doubleToLongBits(%1$s) "+(not ? "!=" : "==")+" Double.doubleToLongBits(%2$s)";
|
||||
case FLOAT: return "Float.floatToIntBits(%1$s) "+(not ? "!=" : "==")+" Float.floatToIntBits(%2$s)";
|
||||
case OBJECT: return (not ? "!" : "")+"Objects.equals(%1$s, %2$s)";
|
||||
default: return "%1$s "+(not ? "!=" : "==")+" %2$s";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,13 +52,16 @@ public class GlobalVariables
|
|||
public GlobalVariables createHelperVariables()
|
||||
{
|
||||
addArgumentMapper("EQUALS_KEY_TYPE", type.isObject() ? "Objects.equals(%2$s, %1$s)" : "Objects.equals(%2$s, KEY_TO_OBJ(%1$s))").removeBraces();
|
||||
addArgumentMapper("EQUALS", type.getEquals()).removeBraces();
|
||||
addInjectMapper("EQUALS_NOT_NULL", type.getComparableValue()+" != "+(type.isPrimitiveBlocking() ? type.getEmptyValue() : (type.needsCast() ? type.getEmptyValue() : "0"))).removeBraces();
|
||||
addInjectMapper("EQUALS_NULL", type.getComparableValue()+" == "+(type.isPrimitiveBlocking() ? type.getEmptyValue() : (type.needsCast() ? type.getEmptyValue() : "0"))).removeBraces();
|
||||
addArgumentMapper("EQUALS_NOT", type.getEquals(true)).removeBraces();
|
||||
addArgumentMapper("EQUALS", type.getEquals(false)).removeBraces();
|
||||
addArgumentMapper("COMPARE_TO", type.isObject() ? "%1$s.compareTo(%2$s)" : type.getClassType()+".compare(%1$s, %2$s)").removeBraces();
|
||||
addInjectMapper("KEY_TO_OBJ", type.isObject() ? "%s" : type.getClassType()+".valueOf(%s)").removeBraces();
|
||||
addInjectMapper("OBJ_TO_KEY", type.isObject() ? "%s" : "%s."+type.getKeyType()+"Value()").removeBraces();
|
||||
addInjectMapper("CLASS_TO_KEY", "(("+type.getClassType()+")%s)."+type.getKeyType()+"Value()").removeBraces();
|
||||
addSimpleMapper("APPLY", "applyAs"+type.getCustomJDKType().getNonFileType());
|
||||
addInjectMapper("HASH", type.getClassType()+".hashCode(%s)").removeBraces();
|
||||
addInjectMapper("TO_HASH", type.isObject() ? "%s.hashCode()" : type.getClassType()+".hashCode(%s)").removeBraces();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -67,6 +70,34 @@ public class GlobalVariables
|
|||
addSimpleMapper("JAVA_PREDICATE", type.isPrimitiveBlocking() ? "" : type.getCustomJDKType().getFileType()+"Predicate");
|
||||
addSimpleMapper("JAVA_CONSUMER", type.isPrimitiveBlocking() ? "" : "java.util.function."+type.getCustomJDKType().getFileType()+"Consumer");
|
||||
addSimpleMapper("UNARY_OPERATOR", type.isObject() ? "" : type == ClassType.BOOLEAN ? "BinaryOperator" : type.getCustomJDKType().getFileType()+"UnaryOperator");
|
||||
|
||||
//Final Classes
|
||||
addClassMapper("ARRAY_LIST", "ArrayList");
|
||||
addClassMapper("LINKED_HASH_SET", "LinkedOpenHashSet");
|
||||
addClassMapper("HASH_SET", "OpenHashSet");
|
||||
|
||||
//Abstract Classes
|
||||
addClassMapper("ABSTRACT_COLLECTION", "AbstractCollection");
|
||||
addClassMapper("ABSTRACT_SET", "AbstractSet");
|
||||
addClassMapper("ABSTRACT_LIST", "AbstractList");
|
||||
addClassMapper("SUB_LIST", "SubList");
|
||||
|
||||
//Helper Classes
|
||||
addClassMapper("LISTS", "Lists");
|
||||
addClassMapper("COLLECTIONS", "Collections");
|
||||
addClassMapper("ARRAYS", "Arrays");
|
||||
addClassMapper("ITERATORS", "Iterators");
|
||||
|
||||
//Interfaces
|
||||
addClassMapper("LIST_ITERATOR", "ListIterator");
|
||||
addClassMapper("BI_ITERATOR", "BidirectionalIterator");
|
||||
addClassMapper("ITERATOR", "Iterator");
|
||||
addClassMapper("ITERABLE", "Iterable");
|
||||
addClassMapper("COLLECTION", "Collection");
|
||||
addClassMapper("LIST", "List");
|
||||
addClassMapper("SORTED_SET", "SortedSet");
|
||||
addClassMapper("SET", "Set");
|
||||
addClassMapper("STACK", "Stack");
|
||||
if(type.isObject())
|
||||
{
|
||||
addSimpleMapper("CONSUMER", "Consumer");
|
||||
|
@ -79,22 +110,8 @@ public class GlobalVariables
|
|||
addClassMapper("COMPARATOR", "Comparator");
|
||||
addFunctionMappers("IARRAY", "I%sArray");
|
||||
}
|
||||
addClassMapper("ITERATORS", "Iterators");
|
||||
addClassMapper("BI_ITERATOR", "BidirectionalIterator");
|
||||
addClassMapper("LIST_ITERATOR", "ListIterator");
|
||||
addClassMapper("ITERATOR", "Iterator");
|
||||
addClassMapper("ITERABLE", "Iterable");
|
||||
addClassMapper("ABSTRACT_COLLECTION", "AbstractCollection");
|
||||
addClassMapper("COLLECTIONS", "Collections");
|
||||
addClassMapper("COLLECTION", "Collection");
|
||||
addClassMapper("ARRAYS", "Arrays");
|
||||
addClassMapper("ABSTRACT_LIST", "AbstractList");
|
||||
//Dependency
|
||||
addClassMapper("LIST_ITER", "ListIter");
|
||||
addClassMapper("LISTS", "Lists");
|
||||
addClassMapper("SUB_LIST", "SubList");
|
||||
addClassMapper("ARRAY_LIST", "ArrayList");
|
||||
addClassMapper("LIST", "List");
|
||||
addClassMapper("STACK", "Stack");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -112,6 +129,10 @@ public class GlobalVariables
|
|||
addFunctionMapper("TOP", "top");
|
||||
addFunctionMappers("REPLACE", "replace%ss");
|
||||
addFunctionMappers("SORT", "sort%ss");
|
||||
addFunctionMapper("POLL_FIRST_KEY", "pollFirst");
|
||||
addFunctionMapper("FIRST_KEY", "first");
|
||||
addFunctionMapper("POLL_LAST_KEY", "pollLast");
|
||||
addFunctionMapper("LAST_KEY", "last");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package speiger.src.collections.utils;
|
||||
|
||||
public class HashUtil
|
||||
{
|
||||
public static final int DEFAULT_MIN_CAPACITY = 16;
|
||||
public static final float DEFAULT_LOAD_FACTOR = 0.75F;
|
||||
public static final float FAST_LOAD_FACTOR = 0.5F;
|
||||
public static final float FASTER_LOAD_FACTOR = 0.25F;
|
||||
|
||||
private static final int INT_PHI = 0x9E3779B9;
|
||||
private static final int INV_INT_PHI = 0x144cbc89;
|
||||
|
||||
public static int mix(final int x) {
|
||||
final int h = x * INT_PHI;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int invMix(final int x) {
|
||||
return (x ^ x >>> 16) * INV_INT_PHI;
|
||||
}
|
||||
|
||||
public static int nextPowerOfTwo(int x) {
|
||||
if(x == 0) return 1;
|
||||
x--;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
return (x | x >> 16) + 1;
|
||||
}
|
||||
|
||||
public static long nextPowerOfTwo(long x) {
|
||||
if(x == 0) return 1L;
|
||||
x--;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
return (x | x >> 32) + 1L;
|
||||
}
|
||||
|
||||
public static int arraySize(int size, float loadFactor) {
|
||||
return (int)Math.min(1 << 30, Math.max(2, nextPowerOfTwo((long)Math.ceil(size / loadFactor))));
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@ public interface ITrimmable
|
|||
/**
|
||||
* Trims the original collection down to the size of the current elements
|
||||
*/
|
||||
public default void trim() {
|
||||
trim(0);
|
||||
public default boolean trim() {
|
||||
return trim(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims the original collection down to the size of the current elements or the requested size depending which is bigger
|
||||
* @param size the requested trim size.
|
||||
*/
|
||||
public void trim(int size);
|
||||
public boolean trim(int size);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,6 @@ public interface COMPARATOR extends Comparator<CLASS_TYPE>
|
|||
*/
|
||||
public static COMPARATOR of(Comparator<CLASS_TYPE> c) {
|
||||
Objects.requireNonNull(c);
|
||||
return (K, V) -> c.compare(KEY_TO_OBJ(K), KEY_TO_OBJ(V))
|
||||
return (K, V) -> c.compare(KEY_TO_OBJ(K), KEY_TO_OBJ(V));
|
||||
}
|
||||
}
|
|
@ -192,7 +192,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
|
|||
#if TYPE_OBJECT
|
||||
hashCode = 31 * hashCode + i.next().hashCode();
|
||||
#else
|
||||
hashCode = 31 * hashCode + HASH(i.NEXT());
|
||||
hashCode = 31 * hashCode + TO_HASH(i.NEXT());
|
||||
#endif
|
||||
return hashCode;
|
||||
}
|
||||
|
|
|
@ -637,12 +637,17 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
|
|||
@Override
|
||||
@Primitive
|
||||
public void replaceAll(UnaryOperator<CLASS_TYPE> o) {
|
||||
#if PRIMITIVES
|
||||
Objects.requireNonNull(o);
|
||||
#if TYPE_OBJECT
|
||||
REPLACE(T -> KEY_TO_OBJ(o.APPLY(OBJ_TO_KEY(T))));
|
||||
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
|
||||
REPLACE(T -> OBJ_TO_KEY(o.apply(KEY_TO_OBJ(SanityChecks.SANITY_CAST(T)))));
|
||||
#else
|
||||
for(int i = 0;i<size;i++)
|
||||
data[i] = OBJ_TO_KEY(o.apply(KEY_TO_OBJ(data[i])));
|
||||
REPLACE(T -> OBJ_TO_KEY(o.apply(KEY_TO_OBJ(T))));
|
||||
#endif
|
||||
#else
|
||||
Objects.requireNonNull(o);
|
||||
for(int i = 0;i<size;i++)
|
||||
data[i] = OBJ_TO_KEY(o.apply(KEY_TO_OBJ(data[i])));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -922,14 +927,15 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
|
|||
* @param size the requested trim size.
|
||||
*/
|
||||
@Override
|
||||
public void trim(int size) {
|
||||
if(size > size() || size() == data.length) return;
|
||||
public boolean trim(int size) {
|
||||
if(size > size() || size() == data.length) return false;
|
||||
int value = Math.min(size, size());
|
||||
#if TYPE_OBJECT
|
||||
data = value == 0 ? (KEY_TYPE[])ARRAYS.EMPTY_ARRAY : Arrays.copyOf(data, value);
|
||||
#else
|
||||
data = value == 0 ? ARRAYS.EMPTY_ARRAY : Arrays.copyOf(data, value);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
|
||||
public abstract class ABSTRACT_SET KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION KEY_GENERIC_TYPE implements SET KEY_GENERIC_TYPE
|
||||
{
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 1;
|
||||
ITERATOR KEY_GENERIC_TYPE i = iterator();
|
||||
while(i.hasNext())
|
||||
#if TYPE_OBJECT
|
||||
hashCode = 31 * hashCode + i.next().hashCode();
|
||||
#else
|
||||
hashCode = 31 * hashCode + TO_HASH(i.NEXT());
|
||||
#endif
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this)
|
||||
return true;
|
||||
if (!(o instanceof Set))
|
||||
return false;
|
||||
Set<?> l = (Set<?>)o;
|
||||
if(l.size() != size()) return false;
|
||||
#if !TYPE_OBJECT
|
||||
if(l instanceof SET)
|
||||
{
|
||||
ITERATOR e1 = iterator();
|
||||
ITERATOR e2 = ((SET)l).iterator();
|
||||
while (e1.hasNext() && e2.hasNext()) {
|
||||
if(!(EQUALS(e1.NEXT(), e2.NEXT())))
|
||||
return false;
|
||||
}
|
||||
return !(e1.hasNext() || e2.hasNext());
|
||||
}
|
||||
#endif
|
||||
Iterator<CLASS_TYPE> e1 = iterator();
|
||||
Iterator<?> e2 = l.iterator();
|
||||
while (e1.hasNext() && e2.hasNext()) {
|
||||
if(!Objects.equals(e1.next(), e2.next()))
|
||||
return false;
|
||||
}
|
||||
return !(e1.hasNext() || e2.hasNext());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,562 @@
|
|||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
#endif
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Objects;
|
||||
#endif
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
#endif
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
protected long[] links;
|
||||
protected int firstIndex = -1;
|
||||
protected int lastIndex = -1;
|
||||
|
||||
public LINKED_HASH_SET() {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(int minCapacity) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(int minCapacity, float loadFactor) {
|
||||
super(minCapacity, loadFactor);
|
||||
links = new long[nullIndex + 1];
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(KEY_TYPE[] array) {
|
||||
this(array, 0, array.length, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(KEY_TYPE[] array, float loadFactor) {
|
||||
this(array, 0, array.length, loadFactor);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(KEY_TYPE[] array, int offset, int length) {
|
||||
this(array, offset, length, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(KEY_TYPE[] array, int offset, int length, float loadFactor) {
|
||||
this(length < 0 ? 0 : length);
|
||||
SanityChecks.checkArrayCapacity(array.length, offset, length);
|
||||
for(int i = 0;i<length;i++) add(array[offset+i]);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public LINKED_HASH_SET(Collection<? extends CLASS_TYPE> collection) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public LINKED_HASH_SET(Collection<? extends CLASS_TYPE> collection, float loadFactor) {
|
||||
this(collection.size(), loadFactor);
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(COLLECTION KEY_GENERIC_TYPE collection) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(COLLECTION KEY_GENERIC_TYPE collection, float loadFactor) {
|
||||
this(collection.size());
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(Iterator<CLASS_TYPE> iterator) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(Iterator<CLASS_TYPE> iterator, float loadFactor) {
|
||||
#if !TYPE_OBJECT
|
||||
this(ITERATORS.wrap(iterator), loadFactor);
|
||||
#else
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor);
|
||||
while(iterator.hasNext()) add(iterator.next());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public LINKED_HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator, float loadFactor) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor);
|
||||
while(iterator.hasNext()) add(iterator.NEXT());
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o) {
|
||||
if(EQUALS_NULL(o)) {
|
||||
if(containsNull) {
|
||||
moveToFirstIndex(nullIndex);
|
||||
return false;
|
||||
}
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
while(EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(EQUALS(keys[pos], o)) {
|
||||
moveToFirstIndex(pos);
|
||||
return false;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToLast(KEY_TYPE o) {
|
||||
if(EQUALS_NULL(o)) {
|
||||
if(containsNull) {
|
||||
moveToLastIndex(nullIndex);
|
||||
return false;
|
||||
}
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
while(EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(EQUALS(keys[pos], o)) {
|
||||
moveToLastIndex(pos);
|
||||
return false;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE o) {
|
||||
if(EQUALS_NULL(o)) {
|
||||
if(containsNull) {
|
||||
moveToFirstIndex(nullIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
while(EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(EQUALS(keys[pos], o)) {
|
||||
moveToFirstIndex(pos);
|
||||
return true;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = o;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE o) {
|
||||
if(EQUALS_NULL(o)) {
|
||||
if(containsNull) {
|
||||
moveToLastIndex(nullIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
while(EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(EQUALS(keys[pos], o)) {
|
||||
moveToLastIndex(pos);
|
||||
return true;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = o;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void moveToFirstIndex(int startPos) {
|
||||
if(size == 1 || firstIndex == startPos) return;
|
||||
if(lastIndex == startPos) {
|
||||
lastIndex = (int)(links[startPos] >>> 32);
|
||||
links[lastIndex] |= 0xFFFFFFFFL;
|
||||
}
|
||||
else {
|
||||
long link = links[startPos];
|
||||
int prev = (int) ( link >>> 32 );
|
||||
int next = (int) link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
links[firstIndex] ^= ((links[firstIndex] ^ ((startPos & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[startPos] = ((-1 & 0xFFFFFFFFL) << 32) | (firstIndex & 0xFFFFFFFFL);
|
||||
firstIndex = startPos;
|
||||
}
|
||||
|
||||
protected void moveToLastIndex(int startPos) {
|
||||
if(size == 1 || lastIndex == startPos) return;
|
||||
if(firstIndex == startPos) {
|
||||
firstIndex = (int)links[startPos];
|
||||
links[lastIndex] |= 0xFFFFFFFF00000000L;
|
||||
}
|
||||
else {
|
||||
long link = links[startPos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
links[lastIndex] ^= ((links[lastIndex] ^ (startPos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[startPos] = ((lastIndex & 0xFFFFFFFFL) << 32) | (-1 & 0xFFFFFFFFL);
|
||||
lastIndex = startPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE FIRST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return keys[firstIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
int pos = firstIndex;
|
||||
firstIndex = (int)links[pos];
|
||||
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
|
||||
KEY_TYPE result = keys[pos];
|
||||
size--;
|
||||
if(EQUALS_NULL(result)) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return keys[lastIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
int pos = lastIndex;
|
||||
lastIndex = (int)(links[pos] >>> 32);
|
||||
if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL;
|
||||
KEY_TYPE result = keys[pos];
|
||||
size--;
|
||||
if(EQUALS_NULL(result)) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeAdded(int pos) {
|
||||
if(size == 0) {
|
||||
firstIndex = lastIndex = pos;
|
||||
links[pos] = -1L;
|
||||
}
|
||||
else {
|
||||
links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | (-1 & 0xFFFFFFFFL);
|
||||
lastIndex = pos;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeRemoved(int pos) {
|
||||
if(size == 0) firstIndex = lastIndex = 0;
|
||||
else if(firstIndex == pos) {
|
||||
firstIndex = (int)links[pos];
|
||||
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
|
||||
}
|
||||
else if(lastIndex == pos) {
|
||||
lastIndex = (int)(links[pos] >>> 32);
|
||||
if(0 <= lastIndex) links[pos] |= 0xFFFFFFFFL;
|
||||
}
|
||||
else {
|
||||
long link = links[pos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
if(size == 1) {
|
||||
firstIndex = lastIndex = to;
|
||||
links[to] = -1L;
|
||||
}
|
||||
else if(firstIndex == from) {
|
||||
firstIndex = to;
|
||||
links[(int)links[from]] ^= ((links[(int)links[from]] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[to] = links[from];
|
||||
}
|
||||
else if(lastIndex == from) {
|
||||
lastIndex = to;
|
||||
links[(int)(links[from] >>> 32)] ^= ((links[(int)(links[from] >>> 32)] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[to] = links[from];
|
||||
}
|
||||
else {
|
||||
long link = links[from];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[to] = link;
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
long[] newLinks = new long[newSize + 1];
|
||||
int newPrev = -1;
|
||||
for(int j = size, i = firstIndex, pos = 0, prev = -1;j != 0;) {
|
||||
if(EQUALS_NULL(keys[i])) pos = newSize;
|
||||
else {
|
||||
pos = HashUtil.mix(TO_HASH(keys[i])) & newMask;
|
||||
while(EQUALS_NOT_NULL(newKeys[pos])) pos = ++pos & newMask;
|
||||
}
|
||||
newKeys[pos] = keys[i];
|
||||
if(prev != -1) {
|
||||
newLinks[newPrev] ^= ((newLinks[newPrev] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
newLinks[pos] ^= ((newLinks[pos] ^ ((newPrev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
newPrev = pos;
|
||||
}
|
||||
else {
|
||||
newPrev = firstIndex = pos;
|
||||
newLinks[pos] = -1L;
|
||||
}
|
||||
i = (int)links[prev = i];
|
||||
}
|
||||
links = newLinks;
|
||||
lastIndex = newPrev;
|
||||
if(newPrev != -1) newLinks[newPrev] |= 0xFFFFFFFFL;
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
firstIndex = lastIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new SetIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
|
||||
return new SetIterator(fromElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator() { return null; }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
|
||||
int previous = -1;
|
||||
int next = -1;
|
||||
int current = -1;
|
||||
int index = 0;
|
||||
|
||||
SetIterator() {
|
||||
next = firstIndex;
|
||||
}
|
||||
|
||||
SetIterator(KEY_TYPE from) {
|
||||
if(EQUALS_NULL(from)) {
|
||||
if(containsNull) {
|
||||
next = (int) links[nullIndex];
|
||||
previous = nullIndex;
|
||||
}
|
||||
else throw new NoSuchElementException("The null element is not in the set");
|
||||
}
|
||||
else if(EQUALS(keys[lastIndex], from)) {
|
||||
previous = lastIndex;
|
||||
index = size;
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(TO_HASH(from)) & mask;
|
||||
while(EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(EQUALS(keys[pos], from)) {
|
||||
next = (int)links[pos];
|
||||
previous = pos;
|
||||
break;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
if(previous == -1 && next == -1)
|
||||
throw new NoSuchElementException("The element was not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return previous != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
ensureIndexKnown();
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
ensureIndexKnown();
|
||||
return index - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(current == -1) throw new IllegalStateException();
|
||||
ensureIndexKnown();
|
||||
if(current == previous) {
|
||||
index--;
|
||||
previous = (int)(links[current] >> 32);
|
||||
}
|
||||
else next = (int)links[current];
|
||||
size--;
|
||||
if(previous == -1) firstIndex = next;
|
||||
else links[previous] ^= ((links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
|
||||
if (next == -1) lastIndex = previous;
|
||||
else links[next] ^= ((links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
if(current == nullIndex) {
|
||||
current = -1;
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else {
|
||||
int slot, last, startPos = current;
|
||||
current = -1;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
last = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(EQUALS_NULL((current = keys[startPos]))) {
|
||||
keys[last] = EMPTY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(TO_HASH(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
if(next == startPos) next = last;
|
||||
if(previous == startPos) previous = last;
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
current = previous;
|
||||
previous = (int)(links[current] >> 32);
|
||||
next = current;
|
||||
if(index >= 0) index--;
|
||||
return keys[current];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
current = next;
|
||||
next = (int)(links[current]);
|
||||
previous = current;
|
||||
if(index >= 0) index++;
|
||||
return keys[current];
|
||||
}
|
||||
|
||||
private void ensureIndexKnown() {
|
||||
if(index == -1) {
|
||||
if(previous == -1) {
|
||||
index = 0;
|
||||
}
|
||||
else if(next == -1) {
|
||||
index = size;
|
||||
}
|
||||
else {
|
||||
index = 1;
|
||||
for(int pos = firstIndex;pos != previous;pos = (int)links[pos], index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,379 @@
|
|||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Objects;
|
||||
#endif
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.lists.ARRAY_LIST;
|
||||
import speiger.src.collections.PACKAGE.lists.LIST;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
#endif
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
import speiger.src.collections.utils.ITrimmable;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements ITrimmable
|
||||
{
|
||||
protected transient KEY_TYPE[] keys;
|
||||
protected transient boolean containsNull;
|
||||
protected transient int minCapacity;
|
||||
protected transient int nullIndex;
|
||||
protected transient int maxFill;
|
||||
protected transient int mask;
|
||||
|
||||
protected int size;
|
||||
protected final float loadFactor;
|
||||
|
||||
public HASH_SET() {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(int minCapacity) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(int minCapacity, float loadFactor) {
|
||||
if(minCapacity < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed");
|
||||
if(loadFactor <= 0 || loadFactor >= 1F) throw new IllegalStateException("Load Factor is not between 0 and 1");
|
||||
this.loadFactor = loadFactor;
|
||||
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
|
||||
}
|
||||
|
||||
public HASH_SET(KEY_TYPE[] array) {
|
||||
this(array, 0, array.length, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(KEY_TYPE[] array, float loadFactor) {
|
||||
this(array, 0, array.length, loadFactor);
|
||||
}
|
||||
|
||||
public HASH_SET(KEY_TYPE[] array, int offset, int length) {
|
||||
this(array, offset, length, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(KEY_TYPE[] array, int offset, int length, float loadFactor) {
|
||||
this(length < 0 ? 0 : length);
|
||||
SanityChecks.checkArrayCapacity(array.length, offset, length);
|
||||
for(int i = 0;i<length;i++) add(array[offset+i]);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public HASH_SET(Collection<? extends CLASS_TYPE> collection) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public HASH_SET(Collection<? extends CLASS_TYPE> collection, float loadFactor) {
|
||||
this(collection.size(), loadFactor);
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public HASH_SET(COLLECTION KEY_GENERIC_TYPE collection) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(COLLECTION KEY_GENERIC_TYPE collection, float loadFactor) {
|
||||
this(collection.size());
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public HASH_SET(Iterator<CLASS_TYPE> iterator) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(Iterator<CLASS_TYPE> iterator, float loadFactor) {
|
||||
#if !TYPE_OBJECT
|
||||
this(ITERATORS.wrap(iterator), loadFactor);
|
||||
#else
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor);
|
||||
while(iterator.hasNext()) add(iterator.next());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator, float loadFactor) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor);
|
||||
while(iterator.hasNext()) add(iterator.NEXT());
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
if(EQUALS_NULL(o)) {
|
||||
if(containsNull) return false;
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(EQUALS_NOT_NULL(current)) {
|
||||
if(EQUALS(current, o)) return false;
|
||||
while(EQUALS_NOT_NULL((current = keys[++pos & mask])))
|
||||
if(EQUALS(current, o)) return false;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean addAll(Collection<? extends CLASS_TYPE> c) {
|
||||
if(loadFactor <= 0.5F) ensureCapacity(c.size());
|
||||
else ensureCapacity(c.size() + size());
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
if(loadFactor <= 0.5F) ensureCapacity(c.size());
|
||||
else ensureCapacity(c.size() + size());
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if(EQUALS_NULL(o)) return containsNull;
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(EQUALS_NULL(current)) return false;
|
||||
if(EQUALS(current, o)) return true;
|
||||
while(true) {
|
||||
if(EQUALS_NULL((current = keys[++pos & mask]))) return false;
|
||||
else if(EQUALS(current, o)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if(EQUALS_NULL(o)) return (containsNull ? removeNullIndex() : false);
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(EQUALS_NULL(current)) return false;
|
||||
if(EQUALS(current, o)) return removeIndex(pos);
|
||||
while(true) {
|
||||
if(EQUALS_NULL((current = keys[++pos & mask]))) return false;
|
||||
else if(EQUALS(current, o)) return removeIndex(pos);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE o) {
|
||||
if(EQUALS_NULL(o)) return containsNull;
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(EQUALS_NULL(current)) return false;
|
||||
if(EQUALS(current, o)) return true;
|
||||
while(true) {
|
||||
if(EQUALS_NULL((current = keys[++pos & mask]))) return false;
|
||||
else if(EQUALS(current, o)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
if(EQUALS_NULL(o)) return (containsNull ? removeNullIndex() : false);
|
||||
int pos = HashUtil.mix(TO_HASH(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(EQUALS_NULL(current)) return false;
|
||||
if(EQUALS(current, o)) return removeIndex(pos);
|
||||
while(true) {
|
||||
if(EQUALS_NULL((current = keys[++pos & mask]))) return false;
|
||||
else if(EQUALS(current, o)) return removeIndex(pos);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean trim(int size) {
|
||||
int newSize = HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor));
|
||||
if(newSize >= nullIndex || size >= Math.min((int)Math.ceil(newSize * loadFactor), newSize - 1)) return false;
|
||||
try {
|
||||
rehash(newSize);
|
||||
}
|
||||
catch(OutOfMemoryError e) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ensureCapacity(int newCapacity) {
|
||||
int size = HashUtil.arraySize(newCapacity, loadFactor);
|
||||
if(size > nullIndex) rehash(size);
|
||||
}
|
||||
|
||||
protected boolean removeIndex(int pos) {
|
||||
size--;
|
||||
onNodeRemoved(pos);
|
||||
shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean removeNullIndex() {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_VALUE;
|
||||
size--;
|
||||
onNodeRemoved(nullIndex);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onNodeAdded(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeRemoved(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
|
||||
}
|
||||
|
||||
protected void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(EQUALS_NULL((current = keys[startPos]))) {
|
||||
keys[last] = EMPTY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(TO_HASH(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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]));
|
||||
newKeys[pos] = keys[i];
|
||||
}
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new SetIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if(size == 0) return;
|
||||
size = 0;
|
||||
containsNull = false;
|
||||
Arrays.fill(keys, EMPTY_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private class SetIterator implements ITERATOR KEY_GENERIC_TYPE {
|
||||
int pos = nullIndex;
|
||||
int lastReturned = -1;
|
||||
int count = size;
|
||||
boolean returnNull = containsNull;
|
||||
LIST KEY_GENERIC_TYPE wrapped = null;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return count != 0;
|
||||
}
|
||||
|
||||
@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];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(lastReturned == -1) throw new IllegalStateException();
|
||||
if(lastReturned == nullIndex) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else if(pos >= 0) shiftKeys(pos);
|
||||
else {
|
||||
HASH_SET.this.remove(wrapped.GET_KEY(-pos - 1));
|
||||
return;
|
||||
}
|
||||
size--;
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
private void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(EQUALS_NULL((current = keys[startPos]))) {
|
||||
keys[last] = EMPTY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(TO_HASH(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
if(startPos < last) {
|
||||
if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
|
||||
wrapped.add(keys[pos]);
|
||||
}
|
||||
keys[last] = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
|
||||
public interface SET KEY_GENERIC_TYPE extends Set<CLASS_TYPE>, COLLECTION KEY_GENERIC_TYPE
|
||||
{
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public boolean remove(KEY_TYPE o);
|
||||
|
||||
@Override
|
||||
public default boolean REMOVE_KEY(KEY_TYPE o) {
|
||||
return remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public default boolean add(CLASS_TYPE e) {
|
||||
return COLLECTION.super.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public default boolean contains(Object o) {
|
||||
return COLLECTION.super.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public default boolean remove(Object o) {
|
||||
return COLLECTION.super.remove(o);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.SortedSet;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
#else
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
#endif
|
||||
|
||||
public interface SORTED_SET KEY_GENERIC_TYPE extends SET KEY_GENERIC_TYPE, SortedSet<CLASS_TYPE>
|
||||
{
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o);
|
||||
|
||||
public boolean addAndMoveToLast(KEY_TYPE o);
|
||||
|
||||
public boolean moveToFirst(KEY_TYPE o);
|
||||
|
||||
public boolean moveToLast(KEY_TYPE o);
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator();
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement);
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement);
|
||||
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement);
|
||||
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement);
|
||||
|
||||
public KEY_TYPE FIRST_KEY();
|
||||
|
||||
public KEY_TYPE POLL_FIRST_KEY();
|
||||
|
||||
public KEY_TYPE LAST_KEY();
|
||||
|
||||
public KEY_TYPE POLL_LAST_KEY();
|
||||
|
||||
@Override
|
||||
public default SORTED_SET KEY_GENERIC_TYPE subSet(CLASS_TYPE fromElement, CLASS_TYPE toElement) { return subSet(OBJ_TO_KEY(fromElement), OBJ_TO_KEY(toElement)); }
|
||||
|
||||
@Override
|
||||
public default SORTED_SET KEY_GENERIC_TYPE headSet(CLASS_TYPE toElement) { return headSet(OBJ_TO_KEY(toElement)); }
|
||||
|
||||
@Override
|
||||
public default SORTED_SET KEY_GENERIC_TYPE tailSet(CLASS_TYPE fromElement) { return tailSet(OBJ_TO_KEY(fromElement)); }
|
||||
|
||||
@Override
|
||||
public default CLASS_TYPE first() { return KEY_TO_OBJ(FIRST_KEY()); }
|
||||
|
||||
@Override
|
||||
default CLASS_TYPE last() { return KEY_TO_OBJ(LAST_KEY()); }
|
||||
#else
|
||||
public CLASS_TYPE pollFirst();
|
||||
|
||||
public CLASS_TYPE pollLast();
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(CLASS_TYPE fromElement, CLASS_TYPE toElement);
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(CLASS_TYPE toElement);
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(CLASS_TYPE fromElement);
|
||||
#endif
|
||||
}
|
|
@ -41,6 +41,12 @@ public class ITERATORS
|
|||
return iterator instanceof UnmodifiableListIterator ? iterator : new UnmodifiableListIteratorBRACES(iterator);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public static ITERATOR wrap(Iterator<CLASS_TYPE> iterator) {
|
||||
return iterator instanceof ITERATOR ? (ITERATOR)iterator : new IteratorWrapper(iterator);
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Returns a Array Wrapping iterator
|
||||
* @param a the array that should be wrapped
|
||||
|
@ -182,6 +188,31 @@ public class ITERATORS
|
|||
return index;
|
||||
}
|
||||
|
||||
private static class IteratorWrapper implements ITERATOR
|
||||
{
|
||||
Iterator<CLASS_TYPE> iter;
|
||||
|
||||
public IteratorWrapper(Iterator<CLASS_TYPE> iter) {
|
||||
this.iter = iter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return OBJ_TO_KEY(iter.next());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public CLASS_TYPE next() {
|
||||
return iter.next();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
private static class UnmodifiableListIterator KEY_GENERIC_TYPE implements LIST_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
|
|
|
@ -77,7 +77,7 @@ public class LISTS
|
|||
public void ensureCapacity(int size) { synchronized(mutex) { l.ensureCapacity(size); } }
|
||||
|
||||
@Override
|
||||
public void trim(int size) { synchronized(mutex) { l.trim(size); } }
|
||||
public boolean trim(int size) { synchronized(mutex) { return l.trim(size); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] elements() { synchronized(mutex) { return l.elements(); } }
|
||||
|
|
Loading…
Reference in New Issue