diff --git a/Changelog.md b/Changelog.md
index f88516fc..171dc4ec 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -28,6 +28,9 @@
- Fixed: CustomOpenHashMap.keySet.forEach was basically putting out keys even if they were present
- Fixed: ImmutableMaps issues thanks to the tests. Roughly the same as the rest of the maps
- Fixed: RB/AVLTreeMaps issues. Roughly the same as the rest of the maps
+- Fixed: SubLists are now properly implemented.
+- Fixed: HashSet Iterator bugs now fixed... That was Painful.
+- Added: Tests for Lists and Sets
### Version 0.4.5
- Added: removeAll/retainAll(Collection c, Consumer r) which receives all the elements that got deleted from the collection
diff --git a/README.md b/README.md
index e6e76dba..6cee67fd 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,21 @@ But its focus is a different one.
- Suppliers
- Bi/Consumers
+
+## Current Level of Stability
+Since this is a relatively new Library, stability was not perfect and some areas are not perfect yet.
+Thanks to @ben-manes we now have Roughly 16000 test covering Maps/Sets/Lists.
+These tests cover Javas Collection API completely and ensuring a Stable implementation.
+These freshly added tests allowed me to squash thousands of issues according to Googles Test Library (Guava-Tests).
+These will be expanded on as time goes on.
+
+One know aspect of Instability is SubSets and SubMaps. They require full rewrites to be fully stable.
+So it is not advised to use them until these issues are addressed.
+PriorityQueues are tested separately and ensure basic functionality though GuavaTests are planned.
+They just require a custom implementation to run.
+
+As a summary: Stability is good/excellent, unless you need SubSets/SubMaps
+
## Specialized Functions
New Specialized functions that were added to increase performance or reduce allocations or Quality Of life.
To highlight things that may be wanted.
@@ -121,5 +136,5 @@ to build the jar:
do not combine the commands because they can not be executed at the same time.
## Current Down Sides (Random order)
-- Testing for Sub Maps/Sets/Lists are only in a very basic way tested
+- SubMaps/Set implementation isn't perfect right now. This will be addressed slowly due to rewrites required.
- Documentation is only present at the lowest level for most cases and needs a typo fixing.
\ No newline at end of file
diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/AbstractList.template b/src/builder/resources/speiger/assets/collections/templates/lists/AbstractList.template
index f0076c9e..38026770 100644
--- a/src/builder/resources/speiger/assets/collections/templates/lists/AbstractList.template
+++ b/src/builder/resources/speiger/assets/collections/templates/lists/AbstractList.template
@@ -3,11 +3,15 @@ package speiger.src.collections.PACKAGE.lists;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
+import java.util.NoSuchElementException;
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;
+import speiger.src.collections.PACKAGE.collections.SPLIT_ITERATOR;
+import speiger.src.collections.PACKAGE.utils.SPLIT_ITERATORS;
+import speiger.src.collections.utils.SanityChecks;
/**
* Abstract implementation of the {@link LIST} interface.
@@ -15,9 +19,8 @@ import speiger.src.collections.PACKAGE.collections.ITERATOR;
*/
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)}
+ * A Type-Specific implementation of add function that delegates to {@link List#add(int, Object)}
*/
@Override
public boolean add(KEY_TYPE e) {
@@ -25,6 +28,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
return true;
}
+#if !TYPE_OBJECT
/** {@inheritDoc}
*
This default implementation delegates to the corresponding type-specific function.
* @deprecated Please use the corresponding type-specific function instead.
@@ -213,7 +217,8 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public LIST KEY_GENERIC_TYPE subList(int fromIndex, int toIndex) {
- return new SUB_LIST(this, fromIndex, toIndex);
+ SanityChecks.checkArrayCapacity(size(), fromIndex, toIndex-fromIndex);
+ return new SubList(this, 0, fromIndex, toIndex);
}
@Override
@@ -228,6 +233,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
+ if(index < 0 || index > size()) throw new IndexOutOfBoundsException();
return new LIST_ITER(index);
}
@@ -239,134 +245,128 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
public ABSTRACT_LIST KEY_GENERIC_TYPE copy() { throw new UnsupportedOperationException(); }
- private class SUB_LIST extends ABSTRACT_LIST KEY_GENERIC_TYPE {
- ABSTRACT_LIST KEY_GENERIC_TYPE l;
- int offset;
+ private class SubList extends ABSTRACT_LIST KEY_GENERIC_TYPE
+ {
+ final ABSTRACT_LIST KEY_GENERIC_TYPE list;
+ final int parentOffset;
+ final 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;
+ public SubList(ABSTRACT_LIST KEY_GENERIC_TYPE list, int offset, int from, int to) {
+ this.list = list;
+ this.parentOffset = from;
+ this.offset = offset + from;
+ this.size = to - from;
}
@Override
- public void add(int index, KEY_TYPE e) {
- checkAddRange(index);
- l.add(index+offset, e);
+ public void add(int index, KEY_TYPE element) {
+ checkAddSubRange(index);
+ list.add(parentOffset+index, element);
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;
+ checkAddSubRange(index);
+ int add = c.size();
+ if(add <= 0) return false;
+ list.addAll(parentOffset+index, c);
+ this.size += add;
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;
+ checkAddSubRange(index);
+ int add = c.size();
+ if(add <= 0) return false;
+ list.addAll(parentOffset+index, c);
+ this.size += add;
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 boolean addAll(KEY_TYPE[] e, int offset, int length) {
- if(length <= 0) return false;
- l.addElements(this.offset, e, offset, length);
- offset += length;
+ checkAddSubRange(index);
+ int add = c.size();
+ if(add <= 0) return false;
+ list.addAll(parentOffset+index, c);
+ this.size += add;
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;
+ checkAddSubRange(from);
+ if(length <= 0) return;
+ list.addElements(parentOffset+from, a, offset, length);
+ this.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);
+ SanityChecks.checkArrayCapacity(size, from, length);
+ SanityChecks.checkArrayCapacity(a.length, offset, length);
+ return list.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);
+ if(to-from <= 0) return;
+ checkSubRange(from);
+ checkSubRange(to);
+ list.removeElements(from+parentOffset, to+parentOffset);
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);
+ public K[] extractElements(int from, int to, Class type) {
+ checkSubRange(from);
+ checkSubRange(to);
+ K[] result = list.extractElements(from+parentOffset, to+parentOffset, type);
size -= to - from;
- return a;
+ return result;
}
-
+
#else
@Override
public KEY_TYPE[] extractElements(int from, int to) {
- checkRange(from);
- checkRange(to);
- KEY_TYPE[] a = l.extractElements(from + offset, to + offset);
+ checkSubRange(from);
+ checkSubRange(to);
+ KEY_TYPE[] result = list.extractElements(from+parentOffset, to+parentOffset);
size -= to - from;
- return a;
+ return result;
}
#endif
@Override
public KEY_TYPE GET_KEY(int index) {
- checkRange(index);
- return l.GET_KEY(index + offset);
+ checkSubRange(index);
+ return list.GET_KEY(offset+index);
+ }
+
+ @Override
+ public KEY_TYPE set(int index, KEY_TYPE element) {
+ checkSubRange(index);
+ return list.set(offset+index, element);
}
@Override
- public KEY_TYPE set(int index, KEY_TYPE e) {
- checkRange(index);
- return l.set(index + offset, e);
+ public KEY_TYPE swapRemove(int index) {
+ checkSubRange(index);
+ KEY_TYPE result = list.swapRemove(index+parentOffset);
+ size--;
+ return result;
}
@Override
public KEY_TYPE REMOVE(int index) {
- checkRange(index);
- int temp = l.size();
- KEY_TYPE type = l.REMOVE(index + offset);
- if(l.size() != temp) size--;
- return type;
- }
-
- public KEY_TYPE swapRemove(int index) {
- checkRange(index);
- int temp = l.size();
- KEY_TYPE type = l.swapRemove(index + offset);
- if(l.size() != temp) size--;
- return type;
+ checkSubRange(index);
+ KEY_TYPE result = list.REMOVE(index+parentOffset);
+ size--;
+ return result;
}
@Override
@@ -374,17 +374,114 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
return size;
}
- private void checkRange(int index) {
+ @Override
+ public SPLIT_ITERATOR KEY_GENERIC_TYPE spliterator() { return SPLIT_ITERATORS.createSplititerator(this, 16464); }
+
+ @Override
+ public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
+ if(index < 0 || index > size()) throw new IndexOutOfBoundsException();
+ return new SubListIterator(this, index);
+ }
+
+ @Override
+ public LIST KEY_GENERIC_TYPE subList(int fromIndex, int toIndex) {
+ SanityChecks.checkArrayCapacity(size, fromIndex, toIndex-fromIndex);
+ return new SubList(list, offset, fromIndex, toIndex);
+ }
+
+ protected void checkSubRange(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
- private void checkAddRange(int index) {
+ protected void checkAddSubRange(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
+
+ private class SubListIterator implements LIST_ITERATOR KEY_GENERIC_TYPE
+ {
+ ABSTRACT_LIST KEY_GENERIC_TYPE list;
+ int index;
+ int lastReturned = -1;
+
+ SubListIterator(ABSTRACT_LIST KEY_GENERIC_TYPE list, int index) {
+ this.list = list;
+ this.index = index;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return index < list.size();
+ }
+
+ @Override
+ public KEY_TYPE NEXT() {
+ if(!hasNext()) throw new NoSuchElementException();
+ int i = index++;
+ return list.GET_KEY((lastReturned = i));
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return index > 0;
+ }
+
+ @Override
+ public KEY_TYPE PREVIOUS() {
+ if(!hasPrevious()) throw new NoSuchElementException();
+ index--;
+ return list.GET_KEY((lastReturned = index));
+ }
+
+ @Override
+ public int nextIndex() {
+ return index;
+ }
+
+ @Override
+ public int previousIndex() {
+ return index-1;
+ }
+
+ @Override
+ public void remove() {
+ if(lastReturned == -1) throw new IllegalStateException();
+ list.REMOVE(lastReturned);
+ index = lastReturned;
+ lastReturned = -1;
+ }
+
+ @Override
+ public void set(KEY_TYPE e) {
+ if(lastReturned == -1) throw new IllegalStateException();
+ list.set(lastReturned, e);
+ }
+
+ @Override
+ public void add(KEY_TYPE e) {
+ list.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, (list.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 LIST_ITER implements LIST_ITERATOR KEY_GENERIC_TYPE {
int index;
int lastReturned = -1;
@@ -400,8 +497,9 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public KEY_TYPE NEXT() {
- lastReturned = index;
- return GET_KEY(index++);
+ if(!hasNext()) throw new NoSuchElementException();
+ int i = index++;
+ return GET_KEY((lastReturned = i));
}
@Override
@@ -411,8 +509,9 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public KEY_TYPE PREVIOUS() {
- lastReturned = index;
- return GET_KEY(index--);
+ if(!hasPrevious()) throw new NoSuchElementException();
+ index--;
+ return GET_KEY((lastReturned = index));
}
@Override
@@ -427,25 +526,20 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public void remove() {
- if(lastReturned == -1)
- throw new IllegalStateException();
+ if(lastReturned == -1) throw new IllegalStateException();
ABSTRACT_LIST.this.REMOVE(lastReturned);
- if(lastReturned < index)
- index--;
+ index = lastReturned;
lastReturned = -1;
}
@Override
public void set(KEY_TYPE e) {
- if(lastReturned == -1)
- throw new IllegalStateException();
+ 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;
}
diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template b/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template
index 1c03df26..dcfc7c8f 100644
--- a/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template
+++ b/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template
@@ -1029,6 +1029,7 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
for(int i = 0;i size) a[size] = null;
return a;
}
@@ -1037,6 +1038,7 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
if(a.length < size) a = new KEY_TYPE[size];
System.arraycopy(data, 0, a, 0, size);
+ if (a.length > size) a[size] = EMPTY_KEY_VALUE;
return a;
}
@@ -1138,6 +1140,7 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
+
#if PRIMITIVES
/**
* Returns a Java-Type-Specific Stream to reduce boxing/unboxing.
diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/ImmutableList.template b/src/builder/resources/speiger/assets/collections/templates/lists/ImmutableList.template
index 2d034332..62dd7d66 100644
--- a/src/builder/resources/speiger/assets/collections/templates/lists/ImmutableList.template
+++ b/src/builder/resources/speiger/assets/collections/templates/lists/ImmutableList.template
@@ -5,6 +5,7 @@ import java.util.Arrays;
import java.util.Comparator;
#endif
import java.util.Collection;
+import java.util.NoSuchElementException;
import java.util.Objects;
#if TYPE_OBJECT
import java.util.function.BiFunction;
@@ -381,6 +382,12 @@ public class IMMUTABLE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_T
return result;
}
+ @Override
+ public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
+ if(index < 0 || index > size()) throw new IndexOutOfBoundsException();
+ return new LIST_ITER(index);
+ }
+
@Override
public KEY_TYPE set(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); }
@Override
@@ -447,6 +454,7 @@ public class IMMUTABLE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_T
else if(a.length < data.length) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), data.length);
for(int i = 0,m=data.length;i data.length) a[data.length] = null;
return a;
}
@@ -455,6 +463,7 @@ public class IMMUTABLE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_T
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
if(a.length < data.length) a = new KEY_TYPE[data.length];
System.arraycopy(data, 0, a, 0, data.length);
+ if (a.length > data.length) a[data.length] = EMPTY_KEY_VALUE;
return a;
}
@@ -495,4 +504,69 @@ public class IMMUTABLE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_T
*/
@Override
public SPLIT_ITERATOR KEY_GENERIC_TYPE spliterator() { return SPLIT_ITERATORS.createArraySplititerator(data, data.length, 16464); }
+
+ private class LIST_ITER implements LIST_ITERATOR KEY_GENERIC_TYPE {
+ int index;
+
+ LIST_ITER(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return index < size();
+ }
+
+ @Override
+ public KEY_TYPE NEXT() {
+ if(!hasNext()) throw new NoSuchElementException();
+ return GET_KEY(index++);
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return index > 0;
+ }
+
+ @Override
+ public KEY_TYPE PREVIOUS() {
+ if(!hasPrevious()) throw new NoSuchElementException();
+ return GET_KEY(--index);
+ }
+
+ @Override
+ public int nextIndex() {
+ return index;
+ }
+
+ @Override
+ public int previousIndex() {
+ return index-1;
+ }
+
+ @Override
+ public void remove() { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @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;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template b/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template
index bfd81e53..1f77b1d9 100644
--- a/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template
+++ b/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template
@@ -9,6 +9,7 @@ import java.nio.JAVA_BUFFER;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;
+import java.util.NoSuchElementException;
import java.util.Spliterator;
#if PRIMITIVES
import java.util.Spliterator.JAVA_SPLIT_ITERATOR;
@@ -326,9 +327,8 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
@Primitive
public int indexOf(Object o) {
- if(o == null) return -1;
Entry KEY_GENERIC_TYPE entry = first;
- for(int i = 0;entry != null;entry = entry.next) {
+ for(int i = 0;entry != null;entry = entry.next,i++) {
if(Objects.equals(KEY_TO_OBJ(entry.value), o)) return i;
}
return -1;
@@ -337,9 +337,8 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
@Primitive
public int lastIndexOf(Object o) {
- if(o == null) return -1;
Entry KEY_GENERIC_TYPE entry = last;
- for(int i = size-1;entry != null;entry = entry.prev) {
+ for(int i = size-1;entry != null;entry = entry.prev,i--) {
if(Objects.equals(KEY_TO_OBJ(entry.value), o)) return i;
}
return -1;
@@ -354,7 +353,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public int indexOf(KEY_TYPE e) {
Entry entry = first;
- for(int i = 0;entry != null;entry = entry.next) {
+ for(int i = 0;entry != null;entry = entry.next,i++) {
if(KEY_EQUALS(entry.value, e)) return i;
}
return -1;
@@ -363,26 +362,17 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public int lastIndexOf(KEY_TYPE e) {
Entry entry = last;
- for(int i = size-1;entry != null;entry = entry.prev) {
+ for(int i = size-1;entry != null;entry = entry.prev,i--) {
if(KEY_EQUALS(entry.value, e)) return i;
}
return -1;
}
#endif
- @Override
- public ITERATOR KEY_GENERIC_TYPE iterator() {
- return new ListIter(first, 0);
- }
-
- @Override
- public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() {
- return new ListIter(first, 0);
- }
-
@Override
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
- if(index == size-1) return new ListIter(last, index);
+ if(index < 0 || index > size()) throw new IndexOutOfBoundsException();
+ if(index == size) return new ListIter(null, index);
if(index == 0) return new ListIter(first, index);
return new ListIter(getNode(index), index);
}
@@ -564,7 +554,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public boolean removeFirst(KEY_TYPE e) {
if(size == 0) return false;
- for(Entry KEY_GENERIC_TYPE entry = first;entry.next != null;entry = entry.next) {
+ for(Entry KEY_GENERIC_TYPE entry = first;entry != null;entry = entry.next) {
if(KEY_EQUALS(entry.value, e)) {
unlink(entry);
return true;
@@ -576,7 +566,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public boolean removeLast(KEY_TYPE e) {
if(size == 0) return false;
- for(Entry KEY_GENERIC_TYPE entry = last;entry.prev != null;entry = entry.prev) {
+ for(Entry KEY_GENERIC_TYPE entry = last;entry != null;entry = entry.prev) {
if(KEY_EQUALS(entry.value, e)) {
unlink(entry);
return true;
@@ -615,7 +605,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public boolean REMOVE_SWAP(KEY_TYPE e) {
if(size == 0) return false;
- for(Entry KEY_GENERIC_TYPE entry = last;entry.prev != null;entry = entry.prev) {
+ for(Entry KEY_GENERIC_TYPE entry = last;entry != null;entry = entry.prev) {
if(KEY_EQUALS(entry.value, e)) {
if(entry.next == null) {
unlinkLast(entry);
@@ -649,7 +639,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public boolean remove(Object e) {
if(size <= 0) return false;
- for(Entry KEY_GENERIC_TYPE entry = first;entry.next != null;entry = entry.next) {
+ for(Entry KEY_GENERIC_TYPE entry = first;entry != null;entry = entry.next) {
if(KEY_EQUALS(entry.value, e)) {
unlink(entry);
return true;
@@ -949,6 +939,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
for(Entry KEY_GENERIC_TYPE entry = first;entry != null;entry = entry.next) {
a[i++] = (E)KEY_TO_OBJ(entry.value);
}
+ if (a.length > size) a[size] = null;
return a;
}
@@ -958,8 +949,9 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
if(a.length < size) a = new KEY_TYPE[size];
int i = 0;
for(Entry KEY_GENERIC_TYPE entry = first;entry != null;entry = entry.next) {
- a[i++] = KEY_TO_OBJ(entry.value);
+ a[i++] = entry.value;
}
+ if (a.length > size) a[size] = EMPTY_KEY_VALUE;
return a;
}
@@ -1118,23 +1110,23 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
private class ListIter implements LIST_ITERATOR KEY_GENERIC_TYPE
{
- Entry KEY_GENERIC_TYPE node;
+ Entry KEY_GENERIC_TYPE next;
Entry KEY_GENERIC_TYPE lastReturned;
int index;
- ListIter(Entry KEY_GENERIC_TYPE node, int index) {
- this.node = node;
+ ListIter(Entry KEY_GENERIC_TYPE next, int index) {
+ this.next = next;
this.index = index;
}
@Override
public boolean hasNext() {
- return node != null;
+ return index < size;
}
@Override
public boolean hasPrevious() {
- return node != null;
+ return index > 0;
}
@Override
@@ -1150,23 +1142,26 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public void remove() {
if(lastReturned == null) throw new IllegalStateException();
- if(lastReturned.next == node) index--;
+ Entry KEY_GENERIC_TYPE lastNext = lastReturned.next;
unlink(lastReturned);
+ if (next == lastReturned) next = lastNext;
+ else index--;
lastReturned = null;
}
@Override
public KEY_TYPE PREVIOUS() {
- lastReturned = node;
- node = node.prev;
+ if(!hasPrevious()) throw new NoSuchElementException();
+ lastReturned = next = (next == null) ? last : next.prev;
index--;
return lastReturned.value;
}
@Override
public KEY_TYPE NEXT() {
- lastReturned = node;
- node = node.next;
+ if(!hasNext()) throw new NoSuchElementException();
+ lastReturned = next;
+ next = next.next;
index++;
return lastReturned.value;
}
@@ -1179,11 +1174,10 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public void add(KEY_TYPE e) {
- if(lastReturned == null) throw new IllegalStateException();
- if(node.next == null) linkLast(e);
- else linkBefore(e, node);
- lastReturned = null;
- index++;
+ lastReturned = null;
+ if (next == null) linkLast(e);
+ else linkBefore(e, next);
+ index++;
}
}
diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template
index 591519dc..fb51db76 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template
@@ -1389,6 +1389,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
private class MapIterator {
int pos = nullIndex;
+ int returnedPos = -1;
int lastReturned = -1;
int nextIndex = Integer.MIN_VALUE;
boolean returnNull = containsNull;
@@ -1420,6 +1421,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
public int nextEntry() {
if(!hasNext()) throw new NoSuchElementException();
+ returnedPos = pos;
if(nextIndex < 0){
lastReturned = Integer.MAX_VALUE;
int value = findIndex(wrapped.GET_KEY(nextIndex));
@@ -1439,9 +1441,10 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
keys[nullIndex] = EMPTY_KEY_VALUE;
values[nullIndex] = EMPTY_VALUE;
}
- else if(lastReturned >= 0) shiftKeys(lastReturned);
+ else if(returnedPos >= 0) shiftKeys(returnedPos);
else {
- CUSTOM_HASH_MAP.this.remove(wrapped.GET_KEY(-lastReturned - 1));
+ CUSTOM_HASH_MAP.this.remove(wrapped.GET_KEY(-returnedPos - 1));
+ lastReturned = -1;
return;
}
size--;
diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template
index 65098fd4..d7fc9582 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template
@@ -1345,6 +1345,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
private class MapIterator {
int pos = nullIndex;
+ int returnedPos = -1;
int lastReturned = -1;
int nextIndex = Integer.MIN_VALUE;
boolean returnNull = containsNull;
@@ -1376,6 +1377,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
public int nextEntry() {
if(!hasNext()) throw new NoSuchElementException();
+ returnedPos = pos;
if(nextIndex < 0){
lastReturned = Integer.MAX_VALUE;
int value = findIndex(wrapped.GET_KEY(nextIndex));
@@ -1395,9 +1397,10 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
keys[nullIndex] = EMPTY_KEY_VALUE;
values[nullIndex] = EMPTY_VALUE;
}
- else if(lastReturned >= 0) shiftKeys(lastReturned);
+ else if(returnedPos >= 0) shiftKeys(returnedPos);
else {
- HASH_MAP.this.remove(wrapped.GET_KEY(-lastReturned - 1));
+ HASH_MAP.this.remove(wrapped.GET_KEY(-returnedPos - 1));
+ lastReturned = -1;
return;
}
size--;
diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/immutable/ImmutableOpenHashMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/immutable/ImmutableOpenHashMap.template
index 0139838c..6b7f0b63 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/immutable/ImmutableOpenHashMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/immutable/ImmutableOpenHashMap.template
@@ -261,7 +261,7 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
newValues[pos] = b[i];
continue;
}
- while(KEY_EQUALS_NOT_NULL((current = newKeys[pos = (++pos & mask)]))) {
+ while(KEY_EQUALS_NOT_NULL((current = newKeys[pos = (++pos & newMask)]))) {
if(KEY_EQUALS(current, o)) {
found = false;
newValues[pos] = b[i];
diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/ArrayMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/ArrayMap.template
index 903a022a..e9a40b4e 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/ArrayMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/ArrayMap.template
@@ -202,8 +202,11 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
int index = findIndex(key);
- if(index >= 0) insertIndex(size++, key, value);
- return getDefaultReturnValue();
+ if(index < 0) {
+ insertIndex(size++, key, value);
+ return getDefaultReturnValue();
+ }
+ return values[index];
}
#if VALUE_PRIMITIVES
@@ -463,6 +466,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
+ Objects.requireNonNull(mappingFunction);
int index = findIndex(key);
if(index == -1) {
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, getDefaultReturnValue());
@@ -481,6 +485,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
+ Objects.requireNonNull(mappingFunction);
int index = findIndex(key);
if(index == -1) {
VALUE_TYPE newValue = mappingFunction.GET_VALUE(key);
@@ -488,11 +493,18 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
insertIndex(size++, key, newValue);
return newValue;
}
- return values[index];
+ VALUE_TYPE newValue = values[index];
+ if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
+ newValue = mappingFunction.GET_VALUE(key);
+ if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
+ values[index] = newValue;
+ }
+ return newValue;
}
@Override
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
+ Objects.requireNonNull(valueProvider);
int index = findIndex(key);
if(index == -1) {
VALUE_TYPE newValue = valueProvider.VALUE_GET_KEY();
@@ -500,13 +512,20 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
insertIndex(size++, key, newValue);
return newValue;
}
- return values[index];
+ VALUE_TYPE newValue = values[index];
+ if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
+ newValue = valueProvider.VALUE_GET_KEY();
+ if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
+ values[index] = newValue;
+ }
+ return newValue;
}
@Override
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
+ Objects.requireNonNull(mappingFunction);
int index = findIndex(key);
- if(index == -1) return getDefaultReturnValue();
+ if(index == -1 || VALUE_EQUALS(values[index], getDefaultReturnValue())) return getDefaultReturnValue();
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, values[index]);
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
removeIndex(index);
@@ -518,8 +537,12 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
+ Objects.requireNonNull(mappingFunction);
+#if VALUE_OBJECT
+ Objects.requireNonNull(value);
+#endif
int index = findIndex(key);
- VALUE_TYPE newValue = index == -1 ? value : mappingFunction.APPLY_VALUE(values[index], value);
+ VALUE_TYPE newValue = index == -1 || VALUE_EQUALS(values[index], getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(values[index], value);
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
if(index >= 0)
removeIndex(index);
@@ -535,7 +558,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
for(MAP.Entry KEY_VALUE_GENERIC_TYPE entry : MAPS.fastIterable(m)) {
KEY_TYPE key = entry.ENTRY_KEY();
int index = findIndex(key);
- VALUE_TYPE newValue = index == -1 ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(values[index], entry.ENTRY_VALUE());
+ VALUE_TYPE newValue = index == -1 || VALUE_EQUALS(values[index], getDefaultReturnValue()) ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(values[index], entry.ENTRY_VALUE());
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
if(index >= 0)
removeIndex(index);
@@ -683,21 +706,18 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
#endif
protected int findIndex(Object key, Object value) {
- if(key == null || value == null) return -1;
for(int i = size-1;i>=0;i--)
if(EQUALS_KEY_TYPE(keys[i], key) && EQUALS_VALUE_TYPE(values[i], value)) return i;
return -1;
}
protected int findIndex(Object key) {
- if(key == null) return -1;
for(int i = size-1;i>=0;i--)
if(EQUALS_KEY_TYPE(keys[i], key)) return i;
return -1;
}
protected int findValue(Object value) {
- if(value == null) return -1;
for(int i = size-1;i>=0;i--)
if(EQUALS_VALUE_TYPE(values[i], value)) return i;
return -1;
@@ -1069,21 +1089,18 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
#endif
protected int findIndex(Object key, Object value) {
- if(key == null || value == null) return -1;
for(int i = length-1;i>=0;i--)
if(EQUALS_KEY_TYPE(keys[offset+i], key) && EQUALS_VALUE_TYPE(values[offset+i], value)) return i+offset;
return -1;
}
protected int findIndex(Object key) {
- if(key == null) return -1;
for(int i = length-1;i>=0;i--)
if(EQUALS_KEY_TYPE(keys[offset+i], key)) return i+offset;
return -1;
}
protected int findValue(Object value) {
- if(value == null) return -1;
for(int i = length-1;i>=0;i--)
if(EQUALS_VALUE_TYPE(values[offset+i], value)) return i+offset;
return -1;
@@ -1268,8 +1285,14 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Deprecated
public boolean contains(Object o) {
if(o instanceof Map.Entry) {
- if(o instanceof MAP.Entry) return SubMap.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
- return SubMap.this.containsKey(((Map.Entry, ?>)o).getKey());
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return SubMap.this.findIndex(entry.ENTRY_KEY(), entry.ENTRY_VALUE()) >= 0;
+ }
+ else {
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return ARRAY_MAP.this.findIndex(entry.getKey(), entry.getValue()) >= 0;
+ }
}
return false;
}
@@ -1318,7 +1341,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public boolean remove(Object o) {
int oldSize = length;
- remove(o);
+ SubMap.this.remove(o);
return length != oldSize;
}
@@ -1329,7 +1352,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public boolean remove(KEY_TYPE o) {
int oldSize = length;
- remove(o);
+ SubMap.this.remove(o);
return length != oldSize;
}
@@ -1737,12 +1760,14 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
}
public int previousEntry() {
+ if(!hasPrevious()) throw new NoSuchElementException();
int returnIndex = offset+index;
lastReturned = index--;
return returnIndex;
}
public int nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
int returnIndex = offset+index;
lastReturned = index++;
return returnIndex;
@@ -1944,8 +1969,16 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Deprecated
public boolean contains(Object o) {
if(o instanceof Map.Entry) {
- if(o instanceof MAP.Entry) return ARRAY_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
- return ARRAY_MAP.this.containsKey(((Map.Entry, ?>)o).getKey());
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ int index = ARRAY_MAP.this.findIndex(entry.ENTRY_KEY());
+ if(index >= 0) return VALUE_EQUALS(entry.ENTRY_VALUE(), ARRAY_MAP.this.values[index]);
+ }
+ else {
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ int index = ARRAY_MAP.this.findIndex(entry.getKey());
+ if(index >= 0) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(ARRAY_MAP.this.values[index]));
+ }
}
return false;
}
@@ -1994,7 +2027,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public boolean remove(Object o) {
int oldSize = size;
- remove(o);
+ ARRAY_MAP.this.remove(o);
return size != oldSize;
}
@@ -2005,7 +2038,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public boolean remove(KEY_TYPE o) {
int oldSize = size;
- remove(o);
+ ARRAY_MAP.this.remove(o);
return size != oldSize;
}
@@ -2401,11 +2434,13 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
}
public int previousEntry() {
+ if(!hasPrevious()) throw new NoSuchElementException();
lastReturned = index;
return index--;
}
public int nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
lastReturned = index;
return index++;
}
@@ -2480,7 +2515,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
@Override
public String toString() {
- return KEY_TO_STRING(keys[index]) + "->" + VALUE_TO_STRING(values[index]);
+ return KEY_TO_STRING(keys[index]) + "=" + VALUE_TO_STRING(values[index]);
}
}
}
\ No newline at end of file
diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/EnumMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/EnumMap.template
index 923c26cb..04a69dc2 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/EnumMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/EnumMap.template
@@ -183,6 +183,7 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
#endif
@Override
public boolean containsKey(Object key) {
+ if(!keyType.isInstance(key)) return false;
return isSet(((T)key).ordinal());
}
@@ -190,7 +191,7 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
@Override
public boolean containsValue(Object value) {
for(int i = 0;i> 6] |= (1L << index);
onNodeAdded(index);
+ present[index >> 6] |= (1L << index);
+ size++;
}
protected void clear(int index) {
size--;
@@ -452,7 +488,20 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
@Override
public boolean contains(Object o) {
- if(o instanceof Map.Entry) return containsKey(((Map.Entry, ?>)o).getKey());
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ if(!keyType.isInstance(entry.ENTRY_KEY())) return false;
+ int index = ((T)entry.ENTRY_KEY()).ordinal();
+ if(index >= 0 && ENUM_MAP.this.isSet(index)) return VALUE_EQUALS(entry.ENTRY_VALUE(), ENUM_MAP.this.values[index]);
+ }
+ else {
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ if(!keyType.isInstance(entry.getKey())) return false;
+ int index = ((T)entry.getKey()).ordinal();
+ if(index >= 0 && ENUM_MAP.this.isSet(index)) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(ENUM_MAP.this.values[index]));
+ }
+ }
return false;
}
@@ -548,8 +597,7 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
class EntryIterator extends MapIterator implements ObjectIterator {
@Override
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
- int index = nextEntry();
- return new BasicEntry<>(keys[index], values[index]);
+ return new MapEntry(nextEntry());
}
}
@@ -584,13 +632,74 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
public int nextEntry() {
if(!hasNext()) throw new NoSuchElementException();
lastReturnValue = nextIndex;
- return nextIndex;
+ nextIndex = -1;
+ return lastReturnValue;
}
public void remove() {
if(lastReturnValue == -1) throw new IllegalStateException();
clear(lastReturnValue);
values[lastReturnValue] = EMPTY_VALUE;
+ lastReturnValue = -1;
+ }
+ }
+
+ protected class MapEntry implements MAP.Entry KEY_VALUE_GENERIC_TYPE, Map.Entry {
+ public int index = -1;
+
+ public MapEntry() {}
+ public MapEntry(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public KEY_TYPE ENTRY_KEY() {
+ return keys[index];
+ }
+
+ @Override
+ public VALUE_TYPE ENTRY_VALUE() {
+ return values[index];
+ }
+
+ @Override
+ public VALUE_TYPE setValue(VALUE_TYPE value) {
+ VALUE_TYPE oldValue = values[index];
+ values[index] = value;
+ return oldValue;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(obj instanceof Map.Entry) {
+ if(obj instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)obj;
+ return KEY_EQUALS(keys[index], entry.ENTRY_KEY()) && VALUE_EQUALS(values[index], entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)obj;
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+#if TYPE_OBJECT && VALUE_OBJECT
+ return KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], value);
+#else if TYPE_OBJECT
+ return value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
+#else if VALUE_OBJECT
+ return key instanceof CLASS_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], value);
+#else
+ return key instanceof CLASS_TYPE && value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
+#endif
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return KEY_TO_HASH(keys[index]) ^ VALUE_TO_HASH(values[index]);
+ }
+
+ @Override
+ public String toString() {
+ return KEY_TO_STRING(keys[index]) + "=" + VALUE_TO_STRING(values[index]);
}
}
}
diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/LinkedEnumMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/LinkedEnumMap.template
index 7a0f9921..5b1cd4b9 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/LinkedEnumMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/misc/LinkedEnumMap.template
@@ -109,7 +109,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
links = enumMap.links.clone();
size = enumMap.size;
}
- if(map instanceof ENUM_MAP) {
+ else if(map instanceof ENUM_MAP) {
ENUM_MAP KEY_VALUE_GENERIC_TYPE enumMap = (ENUM_MAP KEY_VALUE_GENERIC_TYPE)map;
keyType = enumMap.keyType;
keys = enumMap.keys;
@@ -156,7 +156,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
links = enumMap.links.clone();
size = enumMap.size;
}
- if(map instanceof ENUM_MAP) {
+ else if(map instanceof ENUM_MAP) {
ENUM_MAP KEY_VALUE_GENERIC_TYPE enumMap = (ENUM_MAP KEY_VALUE_GENERIC_TYPE)map;
keyType = enumMap.keyType;
keys = enumMap.keys;
@@ -519,8 +519,18 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
@Deprecated
public boolean contains(Object o) {
if(o instanceof Map.Entry) {
- if(o instanceof MAP.Entry) return LINKED_ENUM_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
- return LINKED_ENUM_MAP.this.containsKey(((Map.Entry, ?>)o).getKey());
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ if(!keyType.isInstance(entry.ENTRY_KEY())) return false;
+ int index = ((T)entry.ENTRY_KEY()).ordinal();
+ if(index >= 0 && LINKED_ENUM_MAP.this.isSet(index)) return VALUE_EQUALS(entry.ENTRY_VALUE(), LINKED_ENUM_MAP.this.values[index]);
+ }
+ else {
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ if(!keyType.isInstance(entry.getKey())) return false;
+ int index = ((T)entry.getKey()).ordinal();
+ if(index >= 0 && LINKED_ENUM_MAP.this.isSet(index)) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(LINKED_ENUM_MAP.this.values[index]));
+ }
}
return false;
}
@@ -572,7 +582,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
@Override
public boolean remove(Object o) {
int oldSize = size;
- remove(o);
+ LINKED_ENUM_MAP.this.remove(o);
return size != oldSize;
}
@@ -585,7 +595,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
@Override
public boolean remove(T o) {
int oldSize = size;
- remove(o);
+ LINKED_ENUM_MAP.this.remove(o);
return size != oldSize;
}
@@ -887,6 +897,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
previous = (int)(links[current] >>> 32);
}
else next = (int)links[current];
+
size--;
if(previous == -1) firstIndex = next;
else links[previous] ^= ((links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
@@ -894,6 +905,8 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
if (next == -1) lastIndex = previous;
else links[next] ^= ((links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
values[current] = EMPTY_VALUE;
+ present[current >> 6] &= ~(1L << current);
+ current = -1;
}
public int previousEntry() {
@@ -985,7 +998,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
@Override
public String toString() {
- return KEY_TO_STRING(keys[index]) + "->" + VALUE_TO_STRING(values[index]);
+ return KEY_TO_STRING(keys[index]) + "=" + VALUE_TO_STRING(values[index]);
}
}
}
\ No newline at end of file
diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/tree/AVLTreeMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/tree/AVLTreeMap.template
index d5617823..97293231 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/tree/AVLTreeMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/tree/AVLTreeMap.template
@@ -234,7 +234,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
@Override
public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
if(tree == null) {
tree = first = last = new EntryKV_BRACES(key, value, null);
@@ -271,7 +271,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
@Override
public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
if(tree == null) {
tree = first = last = new EntryKV_BRACES(key, value, null);
@@ -309,7 +309,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
@Override
public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
if(tree == null) {
tree = first = last = new EntryKV_BRACES(key, value, null);
@@ -521,7 +521,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
if(entry == null) {
@@ -543,7 +543,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
if(entry == null) {
@@ -564,7 +564,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
Objects.requireNonNull(valueProvider);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
if(entry == null) {
@@ -585,7 +585,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
if(entry == null || VALUE_EQUALS(entry.value, getDefaultReturnValue())) return getDefaultReturnValue();
@@ -602,7 +602,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
VALUE_TYPE newValue = entry == null || VALUE_EQUALS(entry.value, getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(entry.value, value);
@@ -899,6 +899,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
}
}
+ protected void validate(KEY_TYPE k) { compare(k, k); }
protected int compare(KEY_TYPE k, KEY_TYPE v) { return comparator != null ? comparator.compare(k, v) : COMPAREABLE_TO_KEY(k, v);}
/** From CLR */
@@ -1532,13 +1533,13 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
if(o instanceof Map.Entry) {
if(o instanceof MAP.Entry) {
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
- if(entry.getKey() == null) return false;
+ if(entry.getKey() == null && comparator() == null) return false;
AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = m.findNode(entry.ENTRY_KEY());
if(subEntry != null) return VALUE_EQUALS(entry.ENTRY_VALUE(), subEntry.value);
}
else {
Map.Entry, ?> entry = (Map.Entry, ?>)o;
- if(entry.getKey() == null) return false;
+ if(entry.getKey() == null && comparator() == null) return false;
#if !TYPE_OBJECT
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
#endif
@@ -1938,13 +1939,13 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
if(o instanceof Map.Entry) {
if(o instanceof MAP.Entry) {
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
- if(entry.getKey() == null) return false;
+ if(entry.getKey() == null && comparator() == null) return false;
AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = AVL_TREE_MAP.this.findNode(entry.ENTRY_KEY());
if(subEntry != null) return VALUE_EQUALS(entry.ENTRY_VALUE(), subEntry.value);
}
else {
Map.Entry, ?> entry = (Map.Entry, ?>)o;
- if(entry.getKey() == null) return false;
+ if(entry.getKey() == null && comparator() == null) return false;
#if !TYPE_OBJECT
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
#endif
diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/tree/RBTreeMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/tree/RBTreeMap.template
index 763db3e3..7def1a73 100644
--- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/tree/RBTreeMap.template
+++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/tree/RBTreeMap.template
@@ -234,7 +234,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
@Override
public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
if(tree == null) {
tree = first = last = new EntryKV_BRACES(key, value, null);
@@ -271,7 +271,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
@Override
public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
if(tree == null) {
@@ -310,7 +310,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
@Override
public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
if(tree == null) {
tree = first = last = new EntryKV_BRACES(key, value, null);
@@ -521,7 +521,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
if(entry == null) {
@@ -543,7 +543,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
if(entry == null) {
@@ -564,7 +564,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
Objects.requireNonNull(valueProvider);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
if(entry == null) {
@@ -585,7 +585,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
if(entry == null || VALUE_EQUALS(entry.value, getDefaultReturnValue())) return getDefaultReturnValue();
@@ -602,7 +602,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
#if TYPE_OBJECT
- Objects.requireNonNull(key);
+ validate(key);
#endif
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
VALUE_TYPE newValue = entry == null || VALUE_EQUALS(entry.value, getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(entry.value, value);
@@ -905,6 +905,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
}
}
+ protected void validate(KEY_TYPE k) { compare(k, k); }
protected int compare(KEY_TYPE k, KEY_TYPE v) { return comparator != null ? comparator.compare(k, v) : COMPAREABLE_TO_KEY(k, v);}
protected static GENERIC_KEY_VALUE_BRACES boolean isBlack(Entry KEY_VALUE_GENERIC_TYPE p) { return p == null || p.isBlack(); }
protected static GENERIC_KEY_VALUE_BRACES Entry KEY_VALUE_GENERIC_TYPE parentOf(Entry KEY_VALUE_GENERIC_TYPE p) { return (p == null ? null : p.parent); }
@@ -1587,13 +1588,13 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
if(o instanceof Map.Entry) {
if(o instanceof MAP.Entry) {
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
- if(entry.getKey() == null) return false;
+ if(entry.getKey() == null && comparator() == null) return false;
RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = m.findNode(entry.ENTRY_KEY());
if(subEntry != null) return VALUE_EQUALS(entry.ENTRY_VALUE(), subEntry.value);
}
else {
Map.Entry, ?> entry = (Map.Entry, ?>)o;
- if(entry.getKey() == null) return false;
+ if(entry.getKey() == null && comparator() == null) return false;
#if !TYPE_OBJECT
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
#endif
@@ -1993,13 +1994,13 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
if(o instanceof Map.Entry) {
if(o instanceof MAP.Entry) {
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
- if(entry.getKey() == null) return false;
+ if(entry.getKey() == null && comparator() == null) return false;
RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = RB_TREE_MAP.this.findNode(entry.ENTRY_KEY());
if(subEntry != null) return VALUE_EQUALS(entry.ENTRY_VALUE(), subEntry.value);
}
else {
Map.Entry, ?> entry = (Map.Entry, ?>)o;
- if(entry.getKey() == null) return false;
+ if(entry.getKey() == null && comparator() == null) return false;
#if !TYPE_OBJECT
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
#endif
diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/AVLTreeSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/AVLTreeSet.template
index 744cb50f..36029657 100644
--- a/src/builder/resources/speiger/assets/collections/templates/sets/AVLTreeSet.template
+++ b/src/builder/resources/speiger/assets/collections/templates/sets/AVLTreeSet.template
@@ -213,6 +213,9 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
#endif
@Override
public boolean add(KEY_TYPE o) {
+#if TYPE_OBJECT
+ validate(o);
+#endif
if(tree == null) {
tree = first = last = new EntryBRACES(o, null);
size++;
@@ -242,7 +245,7 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
}
fixAfterInsertion(adding);
size++;
- return false;
+ return true;
}
@Override
@@ -652,6 +655,7 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
}
}
+ protected void validate(KEY_TYPE k) { compare(k, k); }
protected int compare(KEY_TYPE k, KEY_TYPE v) { return comparator != null ? comparator.compare(k, v) : COMPAREABLE_TO_KEY(k, v);}
/** From CLR */
diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/ArraySet.template b/src/builder/resources/speiger/assets/collections/templates/sets/ArraySet.template
index 73b50b1c..59512546 100644
--- a/src/builder/resources/speiger/assets/collections/templates/sets/ArraySet.template
+++ b/src/builder/resources/speiger/assets/collections/templates/sets/ArraySet.template
@@ -74,8 +74,8 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
* @throws NegativeArraySizeException if the length is negative
*/
public ARRAY_SET(KEY_TYPE[] array, int length) {
- data = Arrays.copyOf(array, length);
- size = length;
+ this(length);
+ addAll(array, length);
}
/**
@@ -548,6 +548,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
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());
+ if (a.length > size) a[size] = EMPTY_KEY_VALUE;
return a;
}
@@ -568,6 +569,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
else if(a.length < size()) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), size());
for(int i = 0;i size) a[size] = null;
return a;
}
@@ -841,6 +843,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public KEY_TYPE NEXT() {
+ if(!hasNext()) throw new NoSuchElementException();
lastReturned = index;
return data[index++];
}
@@ -852,6 +855,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public KEY_TYPE PREVIOUS() {
+ if(!hasPrevious()) throw new NoSuchElementException();
lastReturned = index;
return data[index--];
}
@@ -924,6 +928,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public KEY_TYPE NEXT() {
+ if(!hasNext()) throw new NoSuchElementException();
lastReturned = index;
return data[index++];
}
@@ -935,6 +940,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public KEY_TYPE PREVIOUS() {
+ if(!hasPrevious()) throw new NoSuchElementException();
lastReturned = index;
return data[index--];
}
@@ -951,11 +957,9 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
@Override
public void remove() {
- if(lastReturned == -1)
- throw new IllegalStateException();
+ if(lastReturned == -1) throw new IllegalStateException();
ARRAY_SET.this.remove(data[lastReturned]);
- if(lastReturned < index)
- index--;
+ if(lastReturned < index) index--;
lastReturned = -1;
}
diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/ImmutableOpenHashSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/ImmutableOpenHashSet.template
index b354566e..f58c11cd 100644
--- a/src/builder/resources/speiger/assets/collections/templates/sets/ImmutableOpenHashSet.template
+++ b/src/builder/resources/speiger/assets/collections/templates/sets/ImmutableOpenHashSet.template
@@ -190,7 +190,18 @@ public class IMMUTABLE_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERI
{
KEY_TYPE o = a[i];
if(KEY_EQUALS_NULL(o)) {
- if(!containsNull) size++;
+ if(!containsNull) {
+ size++;
+ if(prev != -1) {
+ newLinks[prev] ^= ((newLinks[prev] ^ (newSize & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ newLinks[newSize] ^= ((newLinks[newSize] ^ ((prev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ prev = newSize;
+ }
+ else {
+ prev = firstIndex = newSize;
+ newLinks[newSize] = -1L;
+ }
+ }
containsNull = true;
continue;
}
@@ -199,7 +210,7 @@ public class IMMUTABLE_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERI
KEY_TYPE current = newKeys[pos];
if(KEY_EQUALS_NOT_NULL(current)) {
if(KEY_EQUALS(current, o)) continue;
- while(KEY_EQUALS_NOT_NULL((current = newKeys[pos = (++pos & mask)]))) {
+ while(KEY_EQUALS_NOT_NULL((current = newKeys[pos = (++pos & newMask)]))) {
if(KEY_EQUALS(current, o)) {
found = false;
break;
@@ -220,7 +231,7 @@ public class IMMUTABLE_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERI
}
}
}
- nullIndex = size;
+ nullIndex = newSize;
mask = newMask;
keys = newKeys;
links = newLinks;
diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/OpenCustomHashSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/OpenCustomHashSet.template
index f533acdf..e4674724 100644
--- a/src/builder/resources/speiger/assets/collections/templates/sets/OpenCustomHashSet.template
+++ b/src/builder/resources/speiger/assets/collections/templates/sets/OpenCustomHashSet.template
@@ -602,6 +602,7 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
private class SetIterator implements ITERATOR KEY_GENERIC_TYPE {
int pos = nullIndex;
+ int returnedPos = -1;
int lastReturned = -1;
int nextIndex = Integer.MIN_VALUE;
boolean returnNull = containsNull;
@@ -634,6 +635,7 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
@Override
public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException();
+ returnedPos = pos;
if(nextIndex < 0){
lastReturned = Integer.MAX_VALUE;
KEY_TYPE value = wrapped.GET_KEY(nextIndex);
@@ -652,9 +654,10 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
containsNull = false;
keys[nullIndex] = EMPTY_KEY_VALUE;
}
- else if(pos >= 0) shiftKeys(pos);
+ else if(returnedPos >= 0) shiftKeys(returnedPos);
else {
- CUSTOM_HASH_SET.this.remove(wrapped.GET_KEY(-pos - 1));
+ CUSTOM_HASH_SET.this.remove(wrapped.GET_KEY(-returnedPos - 1));
+ lastReturned = -1;
return;
}
size--;
diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/OpenHashSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/OpenHashSet.template
index 61ff7fd5..390b37c6 100644
--- a/src/builder/resources/speiger/assets/collections/templates/sets/OpenHashSet.template
+++ b/src/builder/resources/speiger/assets/collections/templates/sets/OpenHashSet.template
@@ -559,6 +559,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
private class SetIterator implements ITERATOR KEY_GENERIC_TYPE {
int pos = nullIndex;
+ int returnedPos = -1;
int lastReturned = -1;
int nextIndex = Integer.MIN_VALUE;
boolean returnNull = containsNull;
@@ -592,6 +593,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
@Override
public KEY_TYPE NEXT() {
if(!hasNext()) throw new NoSuchElementException();
+ returnedPos = pos;
if(nextIndex < 0){
lastReturned = Integer.MAX_VALUE;
KEY_TYPE value = wrapped.GET_KEY(nextIndex);
@@ -610,9 +612,10 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
containsNull = false;
keys[nullIndex] = EMPTY_KEY_VALUE;
}
- else if(pos >= 0) shiftKeys(pos);
+ else if(returnedPos >= 0) shiftKeys(returnedPos);
else {
- HASH_SET.this.remove(wrapped.GET_KEY(-pos - 1));
+ HASH_SET.this.remove(wrapped.GET_KEY(-returnedPos - 1));
+ lastReturned = -1;
return;
}
size--;
diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/RBTreeSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/RBTreeSet.template
index ebaa06f9..83872ffd 100644
--- a/src/builder/resources/speiger/assets/collections/templates/sets/RBTreeSet.template
+++ b/src/builder/resources/speiger/assets/collections/templates/sets/RBTreeSet.template
@@ -213,6 +213,9 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
#endif
@Override
public boolean add(KEY_TYPE o) {
+#if TYPE_OBJECT
+ validate(o);
+#endif
if(tree == null) {
tree = first = last = new EntryBRACES(o, null);
size++;
@@ -242,7 +245,7 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
}
fixAfterInsertion(adding);
size++;
- return false;
+ return true;
}
@Override
@@ -660,6 +663,7 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
}
}
+ protected void validate(KEY_TYPE k) { compare(k, k); }
protected int compare(KEY_TYPE k, KEY_TYPE v) { return comparator != null ? comparator.compare(k, v) : COMPAREABLE_TO_KEY(k, v);}
protected static GENERIC_KEY_BRACES boolean isBlack(Entry KEY_GENERIC_TYPE p) { return p == null || p.isBlack(); }
protected static GENERIC_KEY_BRACES Entry KEY_GENERIC_TYPE parentOf(Entry KEY_GENERIC_TYPE p) { return (p == null ? null : p.parent); }
diff --git a/src/main/java/speiger/src/collections/utils/SanityChecks.java b/src/main/java/speiger/src/collections/utils/SanityChecks.java
index 04285086..d510dabd 100644
--- a/src/main/java/speiger/src/collections/utils/SanityChecks.java
+++ b/src/main/java/speiger/src/collections/utils/SanityChecks.java
@@ -72,8 +72,8 @@ public class SanityChecks
* @throws IllegalStateException if offset or accessSize is negative or the range goes out of the array-size
*/
public static void checkArrayCapacity(int arraySize, int offset, int accessSize) {
- if(offset < 0) throw new IllegalStateException("Offset is negative ("+offset+")");
- else if(accessSize < 0) throw new IllegalStateException("Size is negative ("+accessSize+")");
+ if(offset < 0) throw new IndexOutOfBoundsException("Offset is negative ("+offset+")");
+ else if(accessSize < 0) throw new IllegalArgumentException("Size is negative ("+accessSize+")");
else if(arraySize < offset + accessSize) throw new IndexOutOfBoundsException("Index (" + (offset + accessSize) + ") is not in size (" + arraySize + ")");
}
diff --git a/src/test/java/speiger/src/collections/objects/list/ObjectListTests.java b/src/test/java/speiger/src/collections/objects/list/ObjectListTests.java
new file mode 100644
index 00000000..7769bdbd
--- /dev/null
+++ b/src/test/java/speiger/src/collections/objects/list/ObjectListTests.java
@@ -0,0 +1,46 @@
+package speiger.src.collections.objects.list;
+
+import java.util.List;
+import java.util.function.Function;
+
+import com.google.common.collect.testing.ListTestSuiteBuilder;
+import com.google.common.collect.testing.TestStringListGenerator;
+import com.google.common.collect.testing.features.CollectionFeature;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.ListFeature;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import speiger.src.collections.objects.lists.ImmutableObjectList;
+import speiger.src.collections.objects.lists.ObjectArrayList;
+import speiger.src.collections.objects.lists.ObjectLinkedList;
+
+@SuppressWarnings("javadoc")
+public class ObjectListTests extends TestCase
+{
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("Lists");
+ suite.addTest(suite("ArrayList", T -> new ObjectArrayList<>(T)));
+ suite.addTest(suite("LinkedList", T -> new ObjectLinkedList<>(T)));
+ suite.addTest(immutableSuite("ImmutableList", T -> new ImmutableObjectList<>(T)));
+ return suite;
+ }
+
+ public static Test suite(String name, Function> factory)
+ {
+ return ListTestSuiteBuilder.using(new TestStringListGenerator() {
+ @Override
+ protected List create(String[] elements) { return factory.apply(elements); }
+ }).named(name).withFeatures(ListFeature.GENERAL_PURPOSE, CollectionFeature.ALLOWS_NULL_VALUES, CollectionSize.ANY).createTestSuite();
+ }
+
+ public static Test immutableSuite(String name, Function> factory)
+ {
+ return ListTestSuiteBuilder.using(new TestStringListGenerator() {
+ @Override
+ protected List create(String[] elements) { return factory.apply(elements); }
+ }).named(name).withFeatures(CollectionFeature.ALLOWS_NULL_VALUES, CollectionSize.ANY).createTestSuite();
+ }
+}
diff --git a/src/test/java/speiger/src/collections/objects/map/ObjectMapTests.java b/src/test/java/speiger/src/collections/objects/map/ObjectMapTests.java
index 62e9c698..6a23916f 100644
--- a/src/test/java/speiger/src/collections/objects/map/ObjectMapTests.java
+++ b/src/test/java/speiger/src/collections/objects/map/ObjectMapTests.java
@@ -6,7 +6,9 @@ import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Supplier;
+import com.google.common.collect.testing.AnEnum;
import com.google.common.collect.testing.MapTestSuiteBuilder;
+import com.google.common.collect.testing.TestEnumMapGenerator;
import com.google.common.collect.testing.TestStringMapGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
@@ -20,6 +22,9 @@ import speiger.src.collections.objects.maps.impl.customHash.Object2ObjectOpenCus
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
import speiger.src.collections.objects.maps.impl.immutable.ImmutableObject2ObjectOpenHashMap;
+import speiger.src.collections.objects.maps.impl.misc.Enum2ObjectMap;
+import speiger.src.collections.objects.maps.impl.misc.LinkedEnum2ObjectMap;
+import speiger.src.collections.objects.maps.impl.misc.Object2ObjectArrayMap;
import speiger.src.collections.objects.maps.impl.tree.Object2ObjectAVLTreeMap;
import speiger.src.collections.objects.maps.impl.tree.Object2ObjectRBTreeMap;
import speiger.src.collections.objects.utils.ObjectStrategy;
@@ -34,9 +39,14 @@ public class ObjectMapTests extends TestCase
suite.addTest(suite("LinkedHashMap", Object2ObjectLinkedOpenHashMap::new, true));
suite.addTest(suite("CustomHashMap", () -> new Object2ObjectOpenCustomHashMap<>(Strategy.INSTANCE), true));
suite.addTest(suite("LinkedCustomHashMap", () -> new Object2ObjectLinkedOpenCustomHashMap<>(Strategy.INSTANCE), true));
- suite.addTest(suite("RBTreeMap", () -> new Object2ObjectRBTreeMap(Comparator.naturalOrder()), false));
- suite.addTest(suite("AVLTreeMap", () -> new Object2ObjectAVLTreeMap(Comparator.naturalOrder()), false));
+ suite.addTest(suite("RBTreeMap_NonNull", Object2ObjectRBTreeMap::new, false));
+ suite.addTest(suite("AVLTreeMap_NonNull", Object2ObjectAVLTreeMap::new, false));
+ suite.addTest(suite("RBTreeMap_Null", () -> new Object2ObjectRBTreeMap<>(Comparator.nullsFirst(Comparator.naturalOrder())), true));
+ suite.addTest(suite("AVLTreeMap_Null", () -> new Object2ObjectAVLTreeMap<>(Comparator.nullsFirst(Comparator.naturalOrder())), true));
suite.addTest(immutableSuit("ImmutableMap", ImmutableObject2ObjectOpenHashMap::new));
+ suite.addTest(suite("ArrayMap", Object2ObjectArrayMap::new, true));
+ suite.addTest(enumSuite("EnumMap", () -> new Enum2ObjectMap<>(AnEnum.class)));
+ suite.addTest(enumSuite("LinkedEnumMap", () -> new LinkedEnum2ObjectMap<>(AnEnum.class)));
return suite;
}
@@ -72,6 +82,21 @@ public class ObjectMapTests extends TestCase
return builder.createTestSuite();
}
+ public static Test enumSuite(String name, Supplier