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:
parent
eaa45976c7
commit
e1df59d512
|
@ -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
|
||||
|
|
17
README.md
17
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.
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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--;
|
||||
|
|
|
@ -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--;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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--;
|
||||
|
|
|
@ -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--;
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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 + ")");
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue