Primitive-Collections/src/builder/resources/speiger/assets/collections/templates/sets/ArraySet.template

903 lines
21 KiB
Plaintext

package speiger.src.collections.PACKAGE.sets;
import java.util.Arrays;
import java.util.Collection;
#if TYPE_OBJECT
import java.util.Comparator;
import java.util.function.Consumer;
#endif
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
#if PRIMITIVES
import java.util.function.JAVA_PREDICATE;
#endif
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
import speiger.src.collections.PACKAGE.collections.COLLECTION;
import speiger.src.collections.PACKAGE.collections.ITERATOR;
import speiger.src.collections.PACKAGE.functions.consumer.BI_OBJECT_CONSUMER;
import speiger.src.collections.PACKAGE.functions.function.PREDICATE;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
import speiger.src.collections.PACKAGE.functions.CONSUMER;
import speiger.src.collections.objects.utils.ObjectArrays;
#endif
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
import speiger.src.collections.PACKAGE.utils.ARRAYS;
/**
* A Type Specific ArraySet implementation.
* That is based around the idea of {@link java.util.List#indexOf(Object)} for no duplication.
* Unless a array constructor is used the ArraySet does not allow for duplication.
* This implementation does not shrink the backing array
* @Type(T)
*/
public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE
{
/** The Backing Array */
protected transient KEY_TYPE[] data;
/** The amount of elements stored in the array*/
protected int size = 0;
/**
* Default Constructor
*/
public ARRAY_SET() {
data = EMPTY_KEY_ARRAY;
}
/**
* Minimum Capacity Constructor
* @param capacity the minimum capacity of the internal array
* @throws NegativeArraySizeException if the capacity is negative
*/
public ARRAY_SET(int capacity) {
data = NEW_KEY_ARRAY(capacity);
}
/**
* Constructur using initial Array
* @param array the array that should be used for set.
*/
public ARRAY_SET(KEY_TYPE[] array) {
this(array, array.length);
}
/**
* Constructur using initial Array
* @param array the array that should be used for set.
* @param length the amount of elements present within the array
* @throws NegativeArraySizeException if the length is negative
*/
public ARRAY_SET(KEY_TYPE[] array, int length) {
data = Arrays.copyOf(array, length);
size = length;
}
/**
* A Helper constructor that allows to create a Set with exactly the same values as the provided collection.
* @param c the elements that should be added to the set.
* @note this slowly checks every element to remove duplicates
*/
@Primitive
public ARRAY_SET(Collection<? extends CLASS_TYPE> c) {
this(c.size());
addAll(c);
}
/**
* A Helper constructor that allows to create a Set with exactly the same values as the provided collection.
* @param c the elements that should be added to the set.
* @note this slowly checks every element to remove duplicates
*/
public ARRAY_SET(COLLECTION KEY_GENERIC_TYPE c) {
this(c.size());
addAll(c);
}
/**
* A Helper constructor that fast copies the element out of a set into the ArraySet.
* Since it is assumed that there is no duplication in the first place
* @param s the set the element should be taken from
*/
@Primitive
public ARRAY_SET(Set<? extends CLASS_TYPE> s) {
this(s.size());
for(CLASS_TYPE e : s)
data[size++] = OBJ_TO_KEY(e);
}
/**
* A Helper constructor that fast copies the element out of a set into the ArraySet.
* Since it is assumed that there is no duplication in the first place
* @param s the set the element should be taken from
*/
public ARRAY_SET(SET KEY_GENERIC_TYPE s) {
this(s.size());
for(ITERATOR KEY_GENERIC_TYPE iter = s.iterator();iter.hasNext();data[size++] = iter.NEXT());
}
@Override
public boolean add(KEY_TYPE o) {
int index = findIndex(o);
if(index == -1) {
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
data[size++] = o;
return true;
}
return false;
}
@Override
public boolean addAndMoveToFirst(KEY_TYPE o) {
int index = findIndex(o);
if(index == -1) {
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
System.arraycopy(data, 0, data, 1, size++);
data[0] = o;
return true;
}
else if(index != 0) {
o = data[index];
System.arraycopy(data, 0, data, 1, index);
data[0] = o;
}
return false;
}
@Override
public boolean addAndMoveToLast(KEY_TYPE o) {
int index = findIndex(o);
if(index == -1) {
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
data[size++] = o;
return true;
}
else if(index != size - 1) {
o = data[index];
System.arraycopy(data, index+1, data, index, size - index);
data[size-1] = o;
}
return false;
}
@Override
public boolean moveToFirst(KEY_TYPE o) {
int index = findIndex(o);
if(index > 0) {
o = data[index];
System.arraycopy(data, 0, data, 1, index);
data[0] = o;
return true;
}
return false;
}
@Override
public boolean moveToLast(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1 && index != size - 1) {
o = data[index];
System.arraycopy(data, index+1, data, index, size - index - 1);
data[size-1] = o;
return true;
}
return false;
}
#if !TYPE_OBJECT
@Override
public boolean contains(KEY_TYPE e) {
return findIndex(e) != -1;
}
#else
@Override
public boolean contains(Object e) {
return findIndex(e) != -1;
}
#endif
@Override
public KEY_TYPE FIRST_KEY() {
if(size == 0) throw new NoSuchElementException();
return data[0];
}
@Override
public KEY_TYPE LAST_KEY() {
if(size == 0) throw new NoSuchElementException();
return data[size - 1];
}
@Override
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c) {
int j = 0;
for(int i = 0;i<size;i++) {
if(!c.contains(data[i]))
data[j++] = data[i];
}
boolean result = j != size;
#if TYPE_OBJECT
Arrays.fill(data, j, size, null);
#endif
size = j;
return result;
}
@Override
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c) {
int j = 0;
for(int i = 0;i<size;i++) {
if(c.contains(data[i]))
data[j++] = data[i];
}
boolean result = j != size;
#if TYPE_OBJECT
Arrays.fill(data, j, size, null);
#endif
size = j;
return result;
}
@Override
@Primitive
public boolean removeAll(Collection<?> c) {
int j = 0;
for(int i = 0;i<size;i++) {
if(!c.contains(KEY_TO_OBJ(data[i])))
data[j++] = data[i];
}
boolean result = j != size;
#if TYPE_OBJECT
Arrays.fill(data, j, size, null);
#endif
size = j;
return result;
}
@Override
@Primitive
public boolean retainAll(Collection<?> c) {
int j = 0;
for(int i = 0;i<size;i++) {
if(c.contains(KEY_TO_OBJ(data[i])))
data[j++] = data[i];
}
boolean result = j != size;
#if TYPE_OBJECT
Arrays.fill(data, j, size, null);
#endif
size = j;
return result;
}
#if !TYPE_OBJECT
@Override
public boolean remove(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1) {
size--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
#if TYPE_OBJECT
data[size] = EMPTY_KEY_VALUE;
#endif
return true;
}
return false;
}
#else
@Override
public boolean remove(Object o) {
int index = findIndex(o);
if(index != -1) {
size--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
#if TYPE_OBJECT
data[size] = EMPTY_KEY_VALUE;
#endif
return true;
}
return false;
}
#endif
@Override
public KEY_TYPE POLL_FIRST_KEY() {
if(size == 0) throw new NoSuchElementException();
KEY_TYPE result = data[0];
System.arraycopy(data, 1, data, 0, --size);
#if TYPE_OBJECT
data[size] = EMPTY_KEY_VALUE;
#endif
return result;
}
@Override
public KEY_TYPE POLL_LAST_KEY() {
if(size == 0) throw new NoSuchElementException();
size--;
#if TYPE_OBJECT
KEY_TYPE result = data[size];
data[size] = EMPTY_KEY_VALUE;
return result;
#else
return data[size];
#endif
}
#if PRIMITIVES
@Override
public boolean remIf(JAVA_PREDICATE KEY_GENERIC_TYPE filter) {
Objects.requireNonNull(filter);
boolean modified = false;
int j = 0;
for(int i = 0;i<size;i++) {
if(!filter.test(data[i])) data[j++] = data[i];
else modified = true;
}
size = j;
return modified;
}
#endif
@Override
public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
Objects.requireNonNull(action);
for(int i = 0;i<size;action.accept(data[i++]));
}
@Override
public <E> void forEach(E input, BI_OBJECT_CONSUMER KEY_VALUE_SPECIAL_GENERIC_TYPE action) {
Objects.requireNonNull(action);
for(int i = 0;i<size;i++)
action.accept(data[i], input);
}
@Override
public boolean matchesAny(PREDICATE KEY_GENERIC_TYPE filter) {
Objects.requireNonNull(filter);
for(int i = 0;i<size;i++) {
if(filter.TEST_VALUE(data[i])) return true;
}
return false;
}
@Override
public boolean matchesNone(PREDICATE KEY_GENERIC_TYPE filter) {
Objects.requireNonNull(filter);
for(int i = 0;i<size;i++) {
if(filter.TEST_VALUE(data[i])) return false;
}
return true;
}
@Override
public boolean matchesAll(PREDICATE KEY_GENERIC_TYPE filter) {
Objects.requireNonNull(filter);
for(int i = 0;i<size;i++) {
if(!filter.TEST_VALUE(data[i])) return false;
}
return true;
}
@Override
public KEY_TYPE findFirst(PREDICATE KEY_GENERIC_TYPE filter) {
Objects.requireNonNull(filter);
for(int i = 0;i<size;i++) {
if(filter.TEST_VALUE(data[i])) return data[i];
}
return EMPTY_VALUE;
}
#if !TYPE_OBJECT
protected int findIndex(KEY_TYPE o) {
for(int i = size-1;i>=0;i--)
if(KEY_EQUALS(data[i], o)) return i;
return -1;
}
#endif
protected int findIndex(Object o) {
for(int i = size-1;i>=0;i--)
if(EQUALS_KEY_TYPE(data[i], o)) return i;
return -1;
}
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
return new SetIterator(0);
}
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
int index = findIndex(fromElement);
if(index != -1) return new SetIterator(index);
throw new NoSuchElementException();
}
@Override
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) {
int fromIndex = findIndex(fromElement);
int toIndex = findIndex(toElement);
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) {
int toIndex = findIndex(toElement);
if(toIndex == -1) throw new NoSuchElementException();
return new SubSet(0, toIndex+1);
}
@Override
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) {
int fromIndex = findIndex(fromElement);
if(fromIndex == -1) throw new NoSuchElementException();
return new SubSet(fromIndex, size - fromIndex);
}
@Override
public COMPARATOR KEY_GENERIC_TYPE comparator() {
return null;
}
@Override
public void clear() {
size = 0;
}
@Override
public int size() {
return size;
}
#if !TYPE_OBJECT
@Override
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
if(a == null || a.length < size()) return Arrays.copyOf(data, size());
System.arraycopy(data, 0, a, 0, size());
return a;
}
#endif
@Override
@Deprecated
public Object[] toArray() {
Object[] obj = new Object[size()];
for(int i = 0;i<size();i++)
obj[i] = KEY_TO_OBJ(data[i]);
return obj;
}
@Override
@Primitive
public <E> E[] toArray(E[] a) {
if(a == null) a = (E[])new Object[size()];
else if(a.length < size()) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), size());
for(int i = 0;i<size();i++)
a[i] = (E)KEY_TO_OBJ(data[i]);
return a;
}
private class SubSet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
int offset;
int length;
SubSet(int offset, int length) {
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(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
if(end() != size) System.arraycopy(data, end(), data, end()+1, size-(offset+length));
data[end()] = o;
size++;
length++;
return true;
}
return false;
}
@Override
public boolean addAndMoveToFirst(KEY_TYPE o) {
int index = findIndex(o);
if(index == -1) {
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
System.arraycopy(data, offset, data, offset+1, size-offset);
data[offset] = o;
size++;
length++;
return true;
}
else if(index != 0) {
o = data[index];
System.arraycopy(data, offset, data, offset+1, index-offset);
data[offset] = o;
}
return false;
}
@Override
public boolean addAndMoveToLast(KEY_TYPE o) {
int index = findIndex(o);
if(index == -1) {
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
System.arraycopy(data, end()+1, data, end(), size-end());
data[end()] = o;
size++;
length++;
return true;
}
else if(index != 0) {
o = data[index];
System.arraycopy(data, offset+1, data, offset, index-offset);
data[offset+length] = o;
}
return false;
}
@Override
public boolean moveToFirst(KEY_TYPE o) {
int index = findIndex(o);
if(index > offset) {
o = data[index];
System.arraycopy(data, offset, data, offset+1, index-offset);
data[offset] = o;
return true;
}
return false;
}
@Override
public boolean moveToLast(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1 && index < end()-1) {
o = data[index];
System.arraycopy(data, index+1, data, index, end()-index-1);
data[end()-1] = o;
return true;
}
return false;
}
#if !TYPE_OBJECT
@Override
public boolean contains(KEY_TYPE e) {
return findIndex(e) != -1;
}
#endif
@Override
public boolean contains(Object e) {
return findIndex(e) != -1;
}
@Override
public KEY_TYPE FIRST_KEY() {
if(length == 0) throw new NoSuchElementException();
return data[offset];
}
@Override
public KEY_TYPE LAST_KEY() {
if(length == 0) throw new NoSuchElementException();
return data[end()-1];
}
#if !TYPE_OBJECT
@Override
public boolean remove(KEY_TYPE o) {
int index = findIndex(o);
if(index != -1) {
size--;
length--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
return true;
}
return false;
}
#endif
@Override
public boolean remove(Object o) {
int index = findIndex(o);
if(index != -1) {
size--;
length--;
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
#if TYPE_OBJECT
data[size] = EMPTY_KEY_VALUE;
#endif
return true;
}
return false;
}
@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] = EMPTY_KEY_VALUE;
#endif
return result;
}
@Override
public KEY_TYPE POLL_LAST_KEY() {
if(length == 0) throw new NoSuchElementException();
KEY_TYPE result = data[offset+length];
size--;
length--;
System.arraycopy(data, end()+1, data, end(), size-end());
#if TYPE_OBJECT
data[size] = EMPTY_KEY_VALUE;
#endif
return result;
}
@Override
public COMPARATOR KEY_GENERIC_TYPE comparator() {
return null;
}
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
return new SetIterator(offset);
}
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
int index = findIndex(fromElement);
if(index != -1) return new SetIterator(index);
throw new NoSuchElementException();
}
@Override
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) {
int fromIndex = findIndex(fromElement);
int toIndex = findIndex(toElement);
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) {
int toIndex = findIndex(toElement);
if(toIndex == -1) throw new NoSuchElementException();
return new SubSet(0, toIndex+1);
}
@Override
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) {
int fromIndex = findIndex(fromElement);
if(fromIndex == -1) throw new NoSuchElementException();
return new SubSet(fromIndex, size - fromIndex);
}
@Override
public int size() {
return length;
}
#if !TYPE_OBJECT
@Override
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
if(a == null || a.length < size()) return Arrays.copyOfRange(data, offset, end());
System.arraycopy(data, offset, a, 0, size());
return a;
}
#endif
@Override
@Deprecated
public Object[] toArray() {
Object[] obj = new Object[size()];
for(int i = 0;i<size();i++)
obj[i] = KEY_TO_OBJ(data[offset+i]);
return obj;
}
@Override
@Primitive
public <E> E[] toArray(E[] a) {
if(a == null) a = (E[])new Object[size()];
else if(a.length < size()) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), size());
for(int i = 0;i<size();i++)
a[i] = (E)KEY_TO_OBJ(data[offset+i]);
return a;
}
#if !TYPE_OBJECT
protected int findIndex(KEY_TYPE o) {
for(int i = length-1;i>=0;i--)
if(KEY_EQUALS(data[offset+i], o)) return i + offset;
return -1;
}
#endif
protected int findIndex(Object o) {
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 {
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();
ARRAY_SET.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;
}
}
}