We are now to 16k tests. Fixed loads of issues.

-Added: Tests for Lists and Sets.
-Fixed: SubLists are now stable (they weren't before)
-Fixed: All the bugs that the unit tests found so far.
-Updated: ReadMe/Changelog
This commit is contained in:
Speiger 2021-12-11 12:53:58 +01:00
parent eaa45976c7
commit e1df59d512
24 changed files with 747 additions and 219 deletions

View File

@ -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

View File

@ -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.

View File

@ -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}
* <p>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> K[] extractElements(int from, int to, Class<K> clz) {
checkRange(from);
checkRange(to);
K[] a = l.extractElements(from + offset, to + offset, clz);
public <K> K[] extractElements(int from, int to, Class<K> 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;
}

View File

@ -1029,6 +1029,7 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
for(int i = 0;i<size;i++)
a[i] = (E)KEY_TO_OBJ(data[i]);
#endif
if (a.length > 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.

View File

@ -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<m;i++)
a[i] = (E)KEY_TO_OBJ(data[i]);
if (a.length > 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;
}
}
}

View File

@ -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++;
}
}

View File

@ -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--;

View File

@ -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--;

View File

@ -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];

View File

@ -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]);
}
}
}

View File

@ -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<values.length;i++)
if(VALUE_EQUALS(value, values[i])) return true;
if(isSet(i) && VALUE_EQUALS(value, values[i])) return true;
return false;
}
@ -198,13 +199,25 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
@Override
public boolean containsValue(VALUE_TYPE value) {
for(int i = 0;i<values.length;i++)
if(VALUE_EQUALS(value, values[i])) return true;
if(isSet(i) && VALUE_EQUALS(value, values[i])) return true;
return false;
}
#endif
@Override
public CLASS_VALUE_TYPE remove(Object key) {
if(!keyType.isInstance(key)) return getDefaultReturnValue();
int index = ((T)key).ordinal();
if(!isSet(index)) return getDefaultReturnValue();
clear(index);
VALUE_TYPE result = values[index];
values[index] = EMPTY_VALUE;
return result;
}
@Override
public VALUE_TYPE rem(T key) {
if(!keyType.isInstance(key)) return getDefaultReturnValue();
int index = key.ordinal();
if(!isSet(index)) return getDefaultReturnValue();
clear(index);
@ -246,6 +259,7 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
#endif
@Override
public VALUE_TYPE GET_VALUE(T key) {
if(!keyType.isInstance(key)) return getDefaultReturnValue();
int index = key.ordinal();
return isSet(index) ? values[index] : getDefaultReturnValue();
}
@ -253,6 +267,7 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
#if VALUE_OBJECT
@Override
public VALUE_TYPE getOrDefault(Object key, VALUE_TYPE defaultValue) {
if(!keyType.isInstance(key)) return defaultValue;
int index = ((T)key).ordinal();
return isSet(index) ? values[index] : defaultValue;
}
@ -260,6 +275,7 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
#else
@Override
public VALUE_TYPE getOrDefault(T key, VALUE_TYPE defaultValue) {
if(!keyType.isInstance(key)) return defaultValue;
int index = key.ordinal();
return isSet(index) ? values[index] : defaultValue;
}
@ -347,7 +363,13 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
values[index] = 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
@ -360,13 +382,19 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
values[index] = 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(T key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
int index = key.ordinal();
if(!isSet(index)) return getDefaultReturnValue();
if(!isSet(index) || VALUE_EQUALS(values[index], getDefaultReturnValue())) return getDefaultReturnValue();
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, values[index]);
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
clear(index);
@ -380,7 +408,10 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
@Override
public VALUE_TYPE MERGE(T key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
int index = key.ordinal();
VALUE_TYPE newValue = !isSet(index) ? value : mappingFunction.APPLY_VALUE(values[index], value);
#if VALUE_OBJECT
Objects.requireNonNull(value);
#endif
VALUE_TYPE newValue = !isSet(index) || VALUE_EQUALS(values[index], getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(values[index], value);
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
if(isSet(index)) {
clear(index);
@ -401,7 +432,7 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
for(MAP.Entry KEY_VALUE_GENERIC_TYPE entry : MAPS.fastIterable(m)) {
T key = entry.ENTRY_KEY();
int index = key.ordinal();
VALUE_TYPE newValue = !isSet(index) ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(values[index], entry.ENTRY_VALUE());
VALUE_TYPE newValue = !isSet(index) || VALUE_EQUALS(values[index], getDefaultReturnValue()) ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(values[index], entry.ENTRY_VALUE());
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
if(isSet(index)) {
clear(index);
@ -424,6 +455,11 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
Arrays.fill(values, EMPTY_VALUE);
}
@Override
public int size() {
return size;
}
protected void onNodeAdded(int index) {
}
@ -433,9 +469,9 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
}
protected void set(int index) {
size++;
present[index >> 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<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
@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<CLASS_TYPE, CLASS_VALUE_TYPE> {
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]);
}
}
}

View File

@ -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]);
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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();i++)
a[i] = (E)KEY_TO_OBJ(data[i]);
if (a.length > 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;
}

View File

@ -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;

View File

@ -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--;

View File

@ -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--;

View File

@ -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); }

View File

@ -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 + ")");
}

View File

@ -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<String[], List<String>> factory)
{
return ListTestSuiteBuilder.using(new TestStringListGenerator() {
@Override
protected List<String> 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<String[], List<String>> factory)
{
return ListTestSuiteBuilder.using(new TestStringListGenerator() {
@Override
protected List<String> create(String[] elements) { return factory.apply(elements); }
}).named(name).withFeatures(CollectionFeature.ALLOWS_NULL_VALUES, CollectionSize.ANY).createTestSuite();
}
}

View File

@ -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<String, String>(Comparator.naturalOrder()), false));
suite.addTest(suite("AVLTreeMap", () -> new Object2ObjectAVLTreeMap<String, String>(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<Map<AnEnum, String>> factory)
{
MapTestSuiteBuilder<AnEnum, String> builder = MapTestSuiteBuilder.using(new TestEnumMapGenerator() {
@Override
protected Map<AnEnum, String> create(Map.Entry<AnEnum, String>[] entries) {
Map<AnEnum, String> map = factory.get();
for(Map.Entry<AnEnum, String> entry : entries) {
map.put(entry.getKey(), entry.getValue());
}
return map;
}
}).named(name).withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE, MapFeature.ALLOWS_NULL_VALUES, CollectionFeature.SUPPORTS_ITERATOR_REMOVE);
return builder.createTestSuite();
}
private static class Strategy implements ObjectStrategy<String>
{
static final Strategy INSTANCE = new Strategy();

View File

@ -0,0 +1,80 @@
package speiger.src.collections.objects.set;
import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import com.google.common.collect.testing.SetTestSuiteBuilder;
import com.google.common.collect.testing.TestStringSetGenerator;
import com.google.common.collect.testing.features.CollectionFeature;
import com.google.common.collect.testing.features.CollectionSize;
import com.google.common.collect.testing.features.SetFeature;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import speiger.src.collections.objects.sets.ImmutableObjectOpenHashSet;
import speiger.src.collections.objects.sets.ObjectAVLTreeSet;
import speiger.src.collections.objects.sets.ObjectArraySet;
import speiger.src.collections.objects.sets.ObjectLinkedOpenCustomHashSet;
import speiger.src.collections.objects.sets.ObjectLinkedOpenHashSet;
import speiger.src.collections.objects.sets.ObjectOpenCustomHashSet;
import speiger.src.collections.objects.sets.ObjectOpenHashSet;
import speiger.src.collections.objects.sets.ObjectRBTreeSet;
import speiger.src.collections.objects.utils.ObjectStrategy;
@SuppressWarnings("javadoc")
public class ObjectSetTests extends TestCase
{
public static Test suite()
{
TestSuite suite = new TestSuite("Sets");
suite.addTest(suite("HashSet", ObjectOpenHashSet::new, true));
suite.addTest(suite("LinkedHashSet", ObjectLinkedOpenHashSet::new, true));
suite.addTest(suite("CustomHashSet", T -> new ObjectOpenCustomHashSet<>(T, Strategy.INSTANCE), true));
suite.addTest(suite("LinkedCustomHashSet", T -> new ObjectLinkedOpenCustomHashSet<>(T, Strategy.INSTANCE), true));
suite.addTest(immutableSuite("ImmutableHashSet", ImmutableObjectOpenHashSet::new));
suite.addTest(suite("ArraySet", ObjectArraySet::new, true));
suite.addTest(suite("RBTreeSet_NonNull", ObjectRBTreeSet::new, false));
suite.addTest(suite("AVLTreeSet_NonNull", ObjectAVLTreeSet::new, false));
suite.addTest(suite("RBTreeSet_Null", T -> new ObjectRBTreeSet<>(T, Comparator.nullsFirst(Comparator.naturalOrder())), true));
suite.addTest(suite("AVLTreeSet_Null", T -> new ObjectAVLTreeSet<>(T, Comparator.nullsFirst(Comparator.naturalOrder())), true));
return suite;
}
public static Test suite(String name, Function<String[], Set<String>> factory, boolean allowNull)
{
SetTestSuiteBuilder<String> generator = SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override
protected Set<String> create(String[] elements) { return factory.apply(elements); }
}).named(name).withFeatures(CollectionSize.ANY, SetFeature.GENERAL_PURPOSE);
if(allowNull) generator.withFeatures(CollectionFeature.ALLOWS_NULL_VALUES);
return generator.createTestSuite();
}
public static Test immutableSuite(String name, Function<String[], Set<String>> factory)
{
return SetTestSuiteBuilder.using(new TestStringSetGenerator() {
@Override
protected Set<String> create(String[] elements) { return factory.apply(elements); }
}).named(name).withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES).createTestSuite();
}
private static class Strategy implements ObjectStrategy<String>
{
static final Strategy INSTANCE = new Strategy();
@Override
public int hashCode(String o) {
return Objects.hashCode(o);
}
@Override
public boolean equals(String key, String value) {
return Objects.equals(key, value);
}
}
}