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 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 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 c) { int j = 0; for(int i = 0;i c) { int j = 0; for(int i = 0;i void forEach(E input, BI_OBJECT_CONSUMER KEY_VALUE_SPECIAL_GENERIC_TYPE action) { Objects.requireNonNull(action); for(int i = 0;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 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 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 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=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; } } }