forked from Speiger/Primitive-Collections
433 lines
11 KiB
Plaintext
433 lines
11 KiB
Plaintext
package speiger.src.collections.PACKAGE.lists;
|
|
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
import java.util.ListIterator;
|
|
import java.util.Objects;
|
|
|
|
import speiger.src.collections.PACKAGE.collections.ABSTRACT_COLLECTION;
|
|
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
|
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
|
|
|
/**
|
|
* Abstract implementation of the {@link LIST} interface.
|
|
*/
|
|
public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION KEY_GENERIC_TYPE implements LIST KEY_GENERIC_TYPE
|
|
{
|
|
#if !TYPE_OBJECT
|
|
/**
|
|
* A Type-Specific implementation of add function that delegates to {@link #add(int, KEY_TYPE)}
|
|
*/
|
|
@Override
|
|
public boolean add(KEY_TYPE e) {
|
|
add(size(), e);
|
|
return true;
|
|
}
|
|
|
|
/** {@inheritDoc}
|
|
* <p>This default implementation delegates to the corresponding type-specific function.
|
|
* @deprecated Please use the corresponding type-specific function instead.
|
|
*/
|
|
@Override
|
|
@Deprecated
|
|
public void add(int index, CLASS_TYPE element) {
|
|
add(index, OBJ_TO_KEY(element));
|
|
}
|
|
|
|
#endif
|
|
/**
|
|
* A Type-Specific implementation that iterates over the elements and adds them.
|
|
* @param c the elements that wants to be added
|
|
* @return true if the list was modified
|
|
*/
|
|
@Override
|
|
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) {
|
|
boolean modified = false;
|
|
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();modified |= add(iter.NEXT()));
|
|
return modified;
|
|
}
|
|
|
|
/**
|
|
* A Type-Specific implementation that iterates over the elements and adds them.
|
|
* @param c the elements that wants to be added
|
|
* @return true if the list was modified
|
|
*/
|
|
@Override
|
|
public boolean addAll(LIST KEY_GENERIC_TYPE c) {
|
|
boolean modified = false;
|
|
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();modified |= add(iter.NEXT()));
|
|
return modified;
|
|
}
|
|
|
|
/**
|
|
* The IndexOf implementation iterates over all elements and compares them to the search value.
|
|
* @param e the value that the index is searched for.
|
|
* @return index of the value that was searched for. -1 if not found
|
|
* @deprecated it is highly suggested not to use this with Primitives because of boxing. But it is still supported because of ObjectComparason that are custom objects and allow to find the contents.
|
|
*/
|
|
@Override
|
|
@Primitive
|
|
public int indexOf(Object o) {
|
|
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
|
#if TYPE_OBJECT
|
|
if(o == null) {
|
|
while(iter.hasNext()) {
|
|
if(iter.NEXT() == null)
|
|
return iter.previousIndex();
|
|
}
|
|
return -1;
|
|
}
|
|
#else
|
|
if(o == null) return -1;
|
|
#endif
|
|
while(iter.hasNext()) {
|
|
if(EQUALS_KEY_TYPE(iter.NEXT(), o))
|
|
return iter.previousIndex();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* The lastIndexOf implementation iterates over all elements and compares them to the search value.
|
|
* @param e the value that the index is searched for.
|
|
* @return the last index of the value that was searched for. -1 if not found
|
|
* @deprecated it is highly suggested not to use this with Primitives because of boxing. But it is still supported because of ObjectComparason that are custom objects and allow to find the contents.
|
|
*/
|
|
@Override
|
|
@Primitive
|
|
public int lastIndexOf(Object o) {
|
|
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator(size());
|
|
#if TYPE_OBJECT
|
|
if(o == null) {
|
|
while(iter.hasPrevious()) {
|
|
if(iter.PREVIOUS() == null)
|
|
return iter.nextIndex();
|
|
}
|
|
return -1;
|
|
}
|
|
#else
|
|
if(o == null) return -1;
|
|
#endif
|
|
while(iter.hasPrevious()) {
|
|
if(EQUALS_KEY_TYPE(iter.PREVIOUS(), o))
|
|
return iter.nextIndex();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#if !TYPE_OBJECT
|
|
/**
|
|
* The indexOf implementation iterates over all elements and compares them to the search value.
|
|
* @param e the value that the index is searched for.
|
|
* @return index of the value that was searched for. -1 if not found
|
|
*/
|
|
@Override
|
|
public int indexOf(KEY_TYPE e) {
|
|
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
|
while(iter.hasNext()) {
|
|
if(KEY_EQUALS(iter.NEXT(), e))
|
|
return iter.previousIndex();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* The lastIndexOf implementation iterates over all elements and compares them to the search value.
|
|
* @param e the value that the index is searched for.
|
|
* @return the last index of the value that was searched for. -1 if not found
|
|
*/
|
|
@Override
|
|
public int lastIndexOf(KEY_TYPE e) {
|
|
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator(size());
|
|
while(iter.hasPrevious()) {
|
|
if(KEY_EQUALS(iter.PREVIOUS(), e))
|
|
return iter.nextIndex();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#endif
|
|
/**
|
|
* Compares if the list are the same.
|
|
*/
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (o == this)
|
|
return true;
|
|
if (!(o instanceof List))
|
|
return false;
|
|
List<?> l = (List<?>)o;
|
|
if(l.size() != size()) return false;
|
|
#if !TYPE_OBJECT
|
|
if(l instanceof LIST)
|
|
{
|
|
LIST_ITERATOR e1 = listIterator();
|
|
LIST_ITERATOR e2 = ((LIST)l).listIterator();
|
|
while (e1.hasNext() && e2.hasNext()) {
|
|
if(!(KEY_EQUALS(e1.NEXT(), e2.NEXT())))
|
|
return false;
|
|
}
|
|
return !(e1.hasNext() || e2.hasNext());
|
|
}
|
|
#endif
|
|
ListIterator<CLASS_TYPE> e1 = listIterator();
|
|
ListIterator<?> e2 = l.listIterator();
|
|
while (e1.hasNext() && e2.hasNext()) {
|
|
if(!Objects.equals(e1.next(), e2.next()))
|
|
return false;
|
|
}
|
|
return !(e1.hasNext() || e2.hasNext());
|
|
}
|
|
|
|
/**
|
|
* Generates the hashcode based on the values stored in the list.
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
int hashCode = 1;
|
|
LIST_ITERATOR KEY_GENERIC_TYPE i = listIterator();
|
|
while(i.hasNext())
|
|
#if TYPE_OBJECT
|
|
hashCode = 31 * hashCode + i.next().hashCode();
|
|
#else
|
|
hashCode = 31 * hashCode + KEY_TO_HASH(i.NEXT());
|
|
#endif
|
|
return hashCode;
|
|
}
|
|
|
|
@Override
|
|
public LIST KEY_GENERIC_TYPE subList(int fromIndex, int toIndex) {
|
|
return new SUB_LIST(this, fromIndex, toIndex);
|
|
}
|
|
|
|
@Override
|
|
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
|
return listIterator(0);
|
|
}
|
|
|
|
@Override
|
|
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() {
|
|
return listIterator(0);
|
|
}
|
|
|
|
@Override
|
|
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
|
|
return new LIST_ITER(index);
|
|
}
|
|
|
|
@Override
|
|
public void size(int size) {
|
|
while(size > size()) add(EMPTY_KEY_VALUE);
|
|
while(size < size()) REMOVE(size() - 1);
|
|
}
|
|
|
|
private class SUB_LIST extends ABSTRACT_LIST KEY_GENERIC_TYPE {
|
|
ABSTRACT_LIST KEY_GENERIC_TYPE l;
|
|
int offset;
|
|
int size;
|
|
|
|
SUB_LIST(ABSTRACT_LIST KEY_GENERIC_TYPE l, int from, int to) {
|
|
if (from < 0) throw new IndexOutOfBoundsException("fromIndex = " + from);
|
|
else if (to > l.size()) throw new IndexOutOfBoundsException("toIndex = " + to);
|
|
else if (from > to) throw new IllegalArgumentException("fromIndex(" + from + ") > toIndex(" + to + ")");
|
|
this.l = l;
|
|
offset = from;
|
|
size = to - from;
|
|
}
|
|
|
|
@Override
|
|
public void add(int index, KEY_TYPE e) {
|
|
checkAddRange(index);
|
|
l.add(index+offset, e);
|
|
size++;
|
|
}
|
|
|
|
@Override
|
|
public boolean addAll(int index, Collection<? extends CLASS_TYPE> c) {
|
|
checkAddRange(index);
|
|
int size = c.size();
|
|
if(size == 0) return false;
|
|
l.addAll(index + offset, l);
|
|
offset += size;
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) {
|
|
checkAddRange(index);
|
|
int size = c.size();
|
|
if(size == 0) return false;
|
|
l.addAll(index + offset, l);
|
|
offset += size;
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) {
|
|
checkAddRange(index);
|
|
int size = c.size();
|
|
if(size == 0) return false;
|
|
l.addAll(index + offset, l);
|
|
offset += size;
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void addElements(int from, KEY_TYPE[] a, int offset, int length) {
|
|
checkRange(from);
|
|
l.addElements(from + this.offset, a, offset, length);
|
|
size += length;
|
|
}
|
|
|
|
@Override
|
|
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) {
|
|
checkRange(from);
|
|
return l.getElements(from + this.offset, a, offset, length);
|
|
}
|
|
|
|
@Override
|
|
public void removeElements(int from, int to) {
|
|
checkRange(from);
|
|
checkRange(to);
|
|
l.removeElements(from + offset, to + offset);
|
|
size -= to - from;
|
|
}
|
|
|
|
#if TYPE_OBJECT
|
|
@Override
|
|
public <K> K[] extractElements(int from, int to, Class<K> clz) {
|
|
checkRange(from);
|
|
checkRange(to);
|
|
K[] a = l.extractElements(from + offset, to + offset, clz);
|
|
size -= to - from;
|
|
return a;
|
|
}
|
|
|
|
#else
|
|
@Override
|
|
public KEY_TYPE[] extractElements(int from, int to) {
|
|
checkRange(from);
|
|
checkRange(to);
|
|
KEY_TYPE[] a = l.extractElements(from + offset, to + offset);
|
|
size -= to - from;
|
|
return a;
|
|
}
|
|
|
|
#endif
|
|
@Override
|
|
public KEY_TYPE GET_KEY(int index) {
|
|
checkRange(index);
|
|
return l.GET_KEY(index + offset);
|
|
}
|
|
|
|
@Override
|
|
public KEY_TYPE set(int index, KEY_TYPE e) {
|
|
checkRange(index);
|
|
return l.set(index + offset, e);
|
|
}
|
|
|
|
@Override
|
|
public KEY_TYPE REMOVE(int index) {
|
|
checkRange(index);
|
|
size--;
|
|
return l.REMOVE(index + offset);
|
|
}
|
|
|
|
@Override
|
|
public int size() {
|
|
return size;
|
|
}
|
|
|
|
private void checkRange(int index) {
|
|
if (index < 0 || index >= size)
|
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
|
}
|
|
|
|
private void checkAddRange(int index) {
|
|
if (index < 0 || index > size)
|
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
|
}
|
|
}
|
|
|
|
private class LIST_ITER implements LIST_ITERATOR KEY_GENERIC_TYPE {
|
|
int index;
|
|
int lastReturned = -1;
|
|
|
|
LIST_ITER(int index) {
|
|
this.index = index;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasNext() {
|
|
return index < size();
|
|
}
|
|
|
|
@Override
|
|
public KEY_TYPE NEXT() {
|
|
lastReturned = index;
|
|
return GET_KEY(index++);
|
|
}
|
|
|
|
@Override
|
|
public boolean hasPrevious() {
|
|
return index > 0;
|
|
}
|
|
|
|
@Override
|
|
public KEY_TYPE PREVIOUS() {
|
|
lastReturned = index;
|
|
return GET_KEY(index--);
|
|
}
|
|
|
|
@Override
|
|
public int nextIndex() {
|
|
return index;
|
|
}
|
|
|
|
@Override
|
|
public int previousIndex() {
|
|
return index-1;
|
|
}
|
|
|
|
@Override
|
|
public void remove() {
|
|
if(lastReturned == -1)
|
|
throw new IllegalStateException();
|
|
ABSTRACT_LIST.this.REMOVE(lastReturned);
|
|
if(lastReturned < index)
|
|
index--;
|
|
lastReturned = -1;
|
|
}
|
|
|
|
@Override
|
|
public void set(KEY_TYPE e) {
|
|
if(lastReturned == -1)
|
|
throw new IllegalStateException();
|
|
ABSTRACT_LIST.this.set(lastReturned, e);
|
|
}
|
|
|
|
@Override
|
|
public void add(KEY_TYPE e) {
|
|
if(lastReturned == -1)
|
|
throw new IllegalStateException();
|
|
ABSTRACT_LIST.this.add(index++, e);
|
|
lastReturned = -1;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
}
|
|
} |