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} *

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 o 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 o 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 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 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[] extractElements(int from, int to, Class 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; } } }