Started massive unit testing library these are the first fixes.

-Fixed: AbstractCollection.retainAll didn't push removed values through the consumer.
-Fixed: AbstractCollection.toArray wouldn't reset the last entry if the input array was larger then the elements in the collection.
-Fixed: SubList didn't check for ranges properly or didn't use parent list to validate changes.
-Fixed: ArrayList.addElements didn't check input array fully and used the wrong variable to move the elements around.
-Fixed: LinkedList.addElements(EmptyInput) would crash.
-Fixed: LinkedList.swapRemove didn't account for if the removed element was the prelast one.
-Fixed: LinkedList.removeElements would break the implementation if the list was almost empty and the middle element was removed.
-Fixed: LinkedHashSet.addAndMoveToFirst wouldn't move elements to the first place.
This commit is contained in:
Speiger 2022-05-22 15:13:29 +02:00
parent 72943cb22c
commit e7da7acc08
8 changed files with 57 additions and 38 deletions

View File

@ -18,7 +18,7 @@ repositories {
} }
archivesBaseName = 'Primitive Collections' archivesBaseName = 'Primitive Collections'
version = '0.6.1'; version = '0.6.1.10';
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = JavaVersion.current(); sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = JavaVersion.current();

View File

@ -230,6 +230,7 @@ public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractColle
for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) { for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) {
KEY_TYPE e = iter.NEXT(); KEY_TYPE e = iter.NEXT();
if(!c.contains(e)) { if(!c.contains(e)) {
r.accept(e);
iter.remove(); iter.remove();
modified = true; modified = true;
} }
@ -256,6 +257,7 @@ public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractColle
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) { public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
if(a == null || a.length < size()) a = new KEY_TYPE[size()]; if(a == null || a.length < size()) a = new KEY_TYPE[size()];
ITERATORS.unwrap(a, iterator()); ITERATORS.unwrap(a, iterator());
if (a.length > size()) a[size()] = EMPTY_KEY_VALUE;
return a; return a;
} }
#endif #endif

View File

@ -315,7 +315,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
public void removeElements(int from, int to) { public void removeElements(int from, int to) {
if(to-from <= 0) return; if(to-from <= 0) return;
checkSubRange(from); checkSubRange(from);
checkSubRange(to); checkAddSubRange(to);
list.removeElements(from+parentOffset, to+parentOffset); list.removeElements(from+parentOffset, to+parentOffset);
size -= to - from; size -= to - from;
} }
@ -324,9 +324,9 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override @Override
public <K> K[] extractElements(int from, int to, Class<K> type) { public <K> K[] extractElements(int from, int to, Class<K> type) {
checkSubRange(from); checkSubRange(from);
checkSubRange(to); checkAddSubRange(to);
K[] result = list.extractElements(from+parentOffset, to+parentOffset, type); K[] result = list.extractElements(from+parentOffset, to+parentOffset, type);
size -= to - from; size -= result.length;
return result; return result;
} }
@ -334,9 +334,9 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override @Override
public KEY_TYPE[] extractElements(int from, int to) { public KEY_TYPE[] extractElements(int from, int to) {
checkSubRange(from); checkSubRange(from);
checkSubRange(to); checkAddSubRange(to);
KEY_TYPE[] result = list.extractElements(from+parentOffset, to+parentOffset); KEY_TYPE[] result = list.extractElements(from+parentOffset, to+parentOffset);
size -= to - from; size -= result.length;
return result; return result;
} }

View File

@ -324,8 +324,9 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
public void addElements(int from, KEY_TYPE[] a, int offset, int length) { public void addElements(int from, KEY_TYPE[] a, int offset, int length) {
if(length <= 0) return; if(length <= 0) return;
checkAddRange(from); checkAddRange(from);
SanityChecks.checkArrayCapacity(a.length, offset, length);
grow(size + length); grow(size + length);
if(from != size) System.arraycopy(data, from, data, from+length, size - length); if(from != size) System.arraycopy(data, from, data, from+length, size - from);
size+=length; size+=length;
System.arraycopy(a, offset, data, from, length); System.arraycopy(a, offset, data, from, length);
} }

View File

@ -365,6 +365,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
KEY_TYPE[] data = this.data; KEY_TYPE[] data = this.data;
int size = data.length; int size = data.length;
if(from < 0 || from > size) throw new IndexOutOfBoundsException("Index: " + from + ", Size: " + size); if(from < 0 || from > size) throw new IndexOutOfBoundsException("Index: " + from + ", Size: " + size);
SanityChecks.checkArrayCapacity(a.length, offset, length);
KEY_TYPE[] newElements; KEY_TYPE[] newElements;
if(from == size) { if(from == size) {
newElements = Arrays.copyOf(data, size+length); newElements = Arrays.copyOf(data, size+length);
@ -1580,7 +1581,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
lock.lock(); lock.lock();
try { try {
checkSubRange(from); checkSubRange(from);
checkSubRange(to); checkAddSubRange(to);
list.removeElements(from+parentOffset, to+parentOffset); list.removeElements(from+parentOffset, to+parentOffset);
size -= to - from; size -= to - from;
} }
@ -1596,9 +1597,9 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
lock.lock(); lock.lock();
try { try {
checkSubRange(from); checkSubRange(from);
checkSubRange(to); checkAddSubRange(to);
K[] result = list.extractElements(from+parentOffset, to+parentOffset, type); K[] result = list.extractElements(from+parentOffset, to+parentOffset, type);
size -= to - from; size -= result.length;
return result; return result;
} }
finally { finally {
@ -1613,9 +1614,9 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
lock.lock(); lock.lock();
try { try {
checkSubRange(from); checkSubRange(from);
checkSubRange(to); checkAddSubRange(to);
KEY_TYPE[] result = list.extractElements(from+parentOffset, to+parentOffset); KEY_TYPE[] result = list.extractElements(from+parentOffset, to+parentOffset);
size -= to - from; size -= result.length;
return result; return result;
} }
finally { finally {

View File

@ -276,6 +276,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override @Override
public void addElements(int from, KEY_TYPE[] a, int offset, int length) { public void addElements(int from, KEY_TYPE[] a, int offset, int length) {
if(length <= 0) return;
SanityChecks.checkArrayCapacity(a.length, offset, length); SanityChecks.checkArrayCapacity(a.length, offset, length);
checkAddRange(from); checkAddRange(from);
Entry KEY_GENERIC_TYPE next; Entry KEY_GENERIC_TYPE next;
@ -617,12 +618,14 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
first = temp; first = temp;
return result; return result;
} }
else if(before.next != last) {
Entry KEY_GENERIC_TYPE temp = last; Entry KEY_GENERIC_TYPE temp = last;
last = temp.prev; last = temp.prev;
last.next = null; last.next = null;
temp.next = before.next; temp.next = before.next;
temp.prev = before; temp.prev = before;
before.next = temp; before.next = temp;
}
return result; return result;
} }
@ -647,12 +650,14 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
first = temp; first = temp;
return true; return true;
} }
else if(before.next != last) {
Entry KEY_GENERIC_TYPE temp = last; Entry KEY_GENERIC_TYPE temp = last;
last = temp.prev; last = temp.prev;
last.next = null; last.next = null;
temp.next = before.next; temp.next = before.next;
temp.prev = before; temp.prev = before;
before.next = temp; before.next = temp;
}
return true; return true;
} }
} }
@ -695,16 +700,18 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
if(from < size - to) { if(from < size - to) {
Entry KEY_GENERIC_TYPE entry = getNode(from); Entry KEY_GENERIC_TYPE entry = getNode(from);
while(length > 0) { while(length > 0) {
entry = entry.next; Entry KEY_GENERIC_TYPE next = entry.next;
unlink(entry.prev); unlink(entry);
entry = next;
length--; length--;
} }
return; return;
} }
Entry KEY_GENERIC_TYPE entry = getNode(to); Entry KEY_GENERIC_TYPE entry = getNode(to);
while(length > 0) { while(length > 0) {
entry = entry.prev; Entry KEY_GENERIC_TYPE prev = entry.prev;
unlink(entry.next); unlink(entry);
entry = prev;
length--; length--;
} }
} }
@ -720,15 +727,17 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
if(from < size - to) { if(from < size - to) {
Entry KEY_GENERIC_TYPE entry = getNode(from); Entry KEY_GENERIC_TYPE entry = getNode(from);
for(int i = 0;length > 0;i++, length--) { for(int i = 0;length > 0;i++, length--) {
entry = entry.next; Entry KEY_GENERIC_TYPE next = entry.next;
a[i] = (K)unlink(entry.prev); a[i] = (K)unlink(entry);
entry = next;
} }
return a; return a;
} }
Entry KEY_GENERIC_TYPE entry = getNode(to); Entry KEY_GENERIC_TYPE entry = getNode(to);
for(int i = length-1;length > 0;i--) { for(int i = length-1;length > 0;i--, length--) {
entry = entry.prev; Entry KEY_GENERIC_TYPE prev = entry.prev;
a[i] = (K)unlink(entry.next); a[i] = (K)unlink(entry);
entry = prev;
} }
return a; return a;
} }
@ -744,15 +753,17 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
if(from < size - to) { if(from < size - to) {
Entry KEY_GENERIC_TYPE entry = getNode(from); Entry KEY_GENERIC_TYPE entry = getNode(from);
for(int i = 0;length > 0;i++, length--) { for(int i = 0;length > 0;i++, length--) {
entry = entry.next; Entry KEY_GENERIC_TYPE next = entry.next;
d[i] = unlink(entry.prev); d[i] = unlink(entry);
entry = next;
} }
return d; return d;
} }
Entry KEY_GENERIC_TYPE entry = getNode(to); Entry KEY_GENERIC_TYPE entry = getNode(to);
for(int i = length-1;length > 0;i--) { for(int i = length-1;length > 0;i--, length--) {
entry = entry.prev; Entry KEY_GENERIC_TYPE prev = entry.prev;
d[i] = unlink(entry.next); d[i] = unlink(entry);
entry = prev;
} }
return d; return d;
} }

View File

@ -237,6 +237,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
} }
containsNull = true; containsNull = true;
onNodeAdded(nullIndex); onNodeAdded(nullIndex);
moveToFirstIndex(nullIndex);
} }
else { else {
int pos = HashUtil.mix(strategy.hashCode(o)) & mask; int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
@ -249,6 +250,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
} }
keys[pos] = o; keys[pos] = o;
onNodeAdded(pos); onNodeAdded(pos);
moveToFirstIndex(pos);
} }
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor)); if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
return true; return true;

View File

@ -208,6 +208,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
} }
containsNull = true; containsNull = true;
onNodeAdded(nullIndex); onNodeAdded(nullIndex);
moveToFirstIndex(nullIndex);
} }
else { else {
int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask; int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask;
@ -220,6 +221,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
} }
keys[pos] = o; keys[pos] = o;
onNodeAdded(pos); onNodeAdded(pos);
moveToFirstIndex(pos);
} }
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor)); if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
return true; return true;