Version 0.7.0 Release

- Added: Coverage Badge
- Updated: Changelog.
- Changed: Changelog now has info how to obtain the sourcecode.
- Added: Over 11 Million Unit Tests to this library to ensure quality.
- Added: ArrayList size constructor now throws IllegalStateException if
the size parameter is negative
- Added: EnumMap specialized forEach implementation.
- Added: AbstractMap.remove now delegates to its primitive counterpart.
- Added: ConcurrentHashMap now implements ITrimmable
- Refactor: Removed a lot of disabled code from ArraySet.
- Removed: LinkedList.addAll(index, List) now delegates to
LinkedList.addAll(index, Collection) due to no special optimization
required.
- Fixed: AbstractList.SubList.get/set/swapRemove didn't calculate their
List index Properly
- Fixed: AbstractList.SubList chains now properly if you create SubLists
within SubLists.
- Fixed: AbstractList.Iterator.add now respects
Immutable/UnmodifiableLists.
- Fixed: AbstractList.Iterator.skip/back now keep track of the last
returned value for remove function to work properly.
- Fixed: CopyOnWriteArrayList.extract/removeElements(int, int) does now
proper range checks and remove elements properly.
- Fixed: CopyOnWriteArrayList.SubList now works properly. (Reimplemented
entirely)
- Fixed: CopyOnWriteArrayList.Iterator.previous() was returning the
wrong values.
- Fixed: CopyOnWriteArrayList.Iterator.skip now skips the right amount
of elements and stops where it should.
- Fixed: LinkedList.first/last/dequeue/dequeueLast now throws
NoSuchElementException when empty instead of IllegalStateException.
- Fixed: LinkedList had an edge case where the entire reverse iterator
would break if the wrong element was removed.
- Fixed: LinkedList.extractElement now returns the correct values.
- Fixed: AbstractMap.entrySet().remove(Object) now returns true if
defaultReturnValue elements were removed.
- Fixed: ConcurrentHashMap.remove(Object, Object) checks if the type
matches before comparing against null Values.
- Fixed: LinkedHashMap.clearAndTrim() was checking the wrong value for
determining the full reset or clearing of a Map.
- Fixed: HashMap.trim/clearToTrim() was using the wrong value to
determin if something should be done.
- Fixed: HashMap now compares empty values (0) against nullKeys when
Object Variants of the type are used.
- Fixed: ImmutableMap now compares empty values (0) against nullKeys
when Object Variants of the type are used.
- Fixed: ArrayMap.iterator(key) now throws NoSuchElementException when
the element wasn't found.
- Fixed: Linked/EnumMap array constructor was creating the wrong size
values array.
- Fixed: LinkedEnumMap.getAndMoveToFirst/Last was moving elements even
if the element wasn't present.
- Fixed: AVL/RBTreeMap.getFirst/LastKey was not throwing a
NoSuchElementException if the map was empty.
- Fixed: Map.Builder wasn't throwing a IllegalStateException when
creating a negative size builder.
- Fixed: AVL/RBTreeSet.DecendingSet.subSet(from, fromInclusive, to,
toInclusive) was creating a corrupt asending subset.
- Fixed: ArraySet throws now a IllegalStateException when trying to
create it with a negative size.
- Fixed: ArraySet.addMoveToLast(key) was crashing when a key was already
present.
- Fixed: Immutable/LinkedHashSet now keep track of their iteration index
properly.
- Fixed: LinkedHashSet.moveToFirst/Last(key) would crash if the Set was
empty.
- Fixed: LinkedHashSet.clearAndTrim() was checking the wrong value for
determining the full reset or clearing of a Map.
- Fixed: HashSet.trim/clearToTrim() was using the wrong value to
determin if something should be done.
This commit is contained in:
2022-06-12 14:31:45 +02:00
parent 8b5e5a75c1
commit ddc58ee221
28 changed files with 642 additions and 539 deletions
@@ -308,7 +308,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) {
SanityChecks.checkArrayCapacity(size, from, length);
SanityChecks.checkArrayCapacity(a.length, offset, length);
return list.getElements(from+this.offset, a, offset, length);
return list.getElements(from+parentOffset, a, offset, length);
}
@Override
@@ -344,19 +344,25 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public KEY_TYPE GET_KEY(int index) {
checkSubRange(index);
return list.GET_KEY(offset+index);
return list.GET_KEY(parentOffset+index);
}
@Override
public KEY_TYPE set(int index, KEY_TYPE element) {
checkSubRange(index);
return list.set(offset+index, element);
return list.set(parentOffset+index, element);
}
@Override
public KEY_TYPE swapRemove(int index) {
checkSubRange(index);
KEY_TYPE result = list.swapRemove(index+parentOffset);
if(index == size-1) {
KEY_TYPE result = list.REMOVE(parentOffset+size-1);
size--;
return result;
}
KEY_TYPE result = list.set(index+parentOffset, list.GET_KEY(parentOffset+size-1));
list.REMOVE(parentOffset+size-1);
size--;
return result;
}
@@ -386,7 +392,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public LIST KEY_GENERIC_TYPE subList(int fromIndex, int toIndex) {
SanityChecks.checkArrayCapacity(size, fromIndex, toIndex-fromIndex);
return new SubList(list, offset, fromIndex, toIndex);
return new SubList(this, offset, fromIndex, toIndex);
}
protected void checkSubRange(int index) {
@@ -460,15 +466,17 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public void add(KEY_TYPE e) {
list.add(index++, e);
list.add(index, e);
index++;
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);
int steps = Math.min(amount, size() - index);
index += steps;
if(steps > 0) lastReturned = Math.min(index-1, size()-1);
return steps;
}
@@ -477,6 +485,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
int steps = Math.min(amount, index);
index -= steps;
if(steps > 0) lastReturned = Math.min(index, size()-1);
return steps;
}
}
@@ -86,6 +86,7 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
* @param size the minimum initial size of the Backing array
*/
public ARRAY_LIST(int size) {
if(size < 0) throw new IllegalStateException("Size has to be 0 or greater");
data = NEW_KEY_ARRAY(size);
}
@@ -9,8 +9,9 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
#if TYPE_OBJECT
import java.util.function.Consumer;
import java.util.function.Supplier;
#if TYPE_OBJECT
import java.util.function.BiFunction;
#endif
import java.util.function.Predicate;
@@ -155,6 +156,14 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
#endif
private void setArray(KEY_TYPE[] data) {
this.data = data;
}
private KEY_TYPE[] getArray() {
return data;
}
/**
* Appends the specified element to the end of this list.
*
@@ -410,6 +419,8 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
*/
@Override
public void removeElements(int from, int to) {
checkRange(from);
checkAddRange(to);
int length = to - from;
if(length <= 0) return;
ReentrantLock lock = this.lock;
@@ -440,9 +451,11 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
*/
@Override
public <K> K[] extractElements(int from, int to, Class<K> type) {
checkRange(from);
checkAddRange(to);
int length = to - from;
if(length <= 0) return ARRAYS.newArray(type, 0);
K[] a = ARRAYS.newArray(type, length);
if(length <= 0) return a;
ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -450,9 +463,9 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
System.arraycopy(data, from, a, 0, length);
if(to == data.length) this.data = Arrays.copyOf(data, data.length - length);
else {
int size = data.length-1;
KEY_TYPE[] newElements = NEW_KEY_ARRAY(size);
System.arraycopy(data, 0, newElements, 0, from);
int size = data.length;
KEY_TYPE[] newElements = NEW_KEY_ARRAY(size-length);
if(from != 0) System.arraycopy(data, 0, newElements, 0, from);
System.arraycopy(data, to, newElements, from, size - to);
this.data = newElements;
}
@@ -472,6 +485,8 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
*/
@Override
public KEY_TYPE[] extractElements(int from, int to) {
checkRange(from);
checkAddRange(to);
int length = to - from;
if(length <= 0) return EMPTY_KEY_ARRAY;
ReentrantLock lock = this.lock;
@@ -482,9 +497,9 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
System.arraycopy(data, from, a, 0, length);
if(to == data.length) this.data = Arrays.copyOf(data, data.length - length);
else {
int size = data.length-1;
KEY_TYPE[] newElements = NEW_KEY_ARRAY(size);
System.arraycopy(data, 0, newElements, 0, from);
int size = data.length;
KEY_TYPE[] newElements = NEW_KEY_ARRAY(size-length);
if(from != 0) System.arraycopy(data, 0, newElements, 0, from);
System.arraycopy(data, to, newElements, from, size - to);
this.data = newElements;
}
@@ -720,7 +735,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public LIST KEY_GENERIC_TYPE subList(int fromIndex, int toIndex) {
SanityChecks.checkArrayCapacity(data.length, fromIndex, toIndex-fromIndex);
return new COWSubListBRACES(this, 0, fromIndex, toIndex);
return new COWSubListBRACES(this, lock, this::setArray, this::getArray, 0, fromIndex, toIndex);
}
/**
@@ -1389,7 +1404,12 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + data.length);
}
#if PRIMITIVES
protected void checkAddRange(int index) {
if (index < 0 || index > data.length)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + data.length);
}
#if PRIMITIVES
/**
* Returns a Java-Type-Specific Stream to reduce boxing/unboxing.
* @return a Stream of the closest java type
@@ -1436,7 +1456,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public KEY_TYPE PREVIOUS() {
if(!hasPrevious()) throw new NoSuchElementException();
return data[index--];
return data[--index];
}
@Override
@@ -1459,7 +1479,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public int skip(int amount) {
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
int steps = Math.min(amount, (data.length - 1) - index);
int steps = Math.min(amount, data.length - index);
index += steps;
return steps;
}
@@ -1475,13 +1495,19 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
private static class COWSubList KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
{
final COPY_ON_WRITE_LIST KEY_GENERIC_TYPE list;
final ABSTRACT_LIST KEY_GENERIC_TYPE list;
final ReentrantLock lock;
final Consumer<KEY_TYPE[]> setter;
final Supplier<KEY_TYPE[]> getter;
final int parentOffset;
final int offset;
int size;
public COWSubList(COPY_ON_WRITE_LIST KEY_GENERIC_TYPE list, int offset, int from, int to) {
public COWSubList(ABSTRACT_LIST KEY_GENERIC_TYPE list, ReentrantLock lock, Consumer<KEY_TYPE[]> setter, Supplier<KEY_TYPE[]> getter, int offset, int from, int to) {
this.list = list;
this.lock = lock;
this.setter = setter;
this.getter = getter;
this.parentOffset = from;
this.offset = offset + from;
this.size = to - from;
@@ -1489,7 +1515,6 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public void add(int index, KEY_TYPE element) {
ReentrantLock lock = list.lock;
lock.lock();
try {
checkAddSubRange(index);
@@ -1505,7 +1530,6 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
public boolean addAll(int index, Collection<? extends CLASS_TYPE> c) {
int add = c.size();
if(add <= 0) return false;
ReentrantLock lock = list.lock;
lock.lock();
try {
checkAddSubRange(index);
@@ -1522,7 +1546,6 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) {
int add = c.size();
if(add <= 0) return false;
ReentrantLock lock = list.lock;
lock.lock();
try {
checkAddSubRange(index);
@@ -1539,7 +1562,6 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) {
int add = c.size();
if(add <= 0) return false;
ReentrantLock lock = list.lock;
lock.lock();
try {
checkAddSubRange(index);
@@ -1555,7 +1577,6 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public void addElements(int from, KEY_TYPE[] a, int offset, int length) {
if(length <= 0) return;
ReentrantLock lock = list.lock;
lock.lock();
try {
checkAddSubRange(from);
@@ -1571,13 +1592,12 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) {
SanityChecks.checkArrayCapacity(size, from, length);
SanityChecks.checkArrayCapacity(a.length, offset, length);
return list.getElements(from+this.offset, a, offset, length);
return list.getElements(from+parentOffset, a, offset, length);
}
@Override
public void removeElements(int from, int to) {
if(to-from <= 0) return;
ReentrantLock lock = list.lock;
lock.lock();
try {
checkSubRange(from);
@@ -1593,7 +1613,6 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
#if TYPE_OBJECT
@Override
public <K> K[] extractElements(int from, int to, Class<K> type) {
ReentrantLock lock = list.lock;
lock.lock();
try {
checkSubRange(from);
@@ -1610,7 +1629,6 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
#else
@Override
public KEY_TYPE[] extractElements(int from, int to) {
ReentrantLock lock = list.lock;
lock.lock();
try {
checkSubRange(from);
@@ -1628,16 +1646,15 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public KEY_TYPE GET_KEY(int index) {
checkSubRange(index);
return list.GET_KEY(offset+index);
return list.GET_KEY(parentOffset+index);
}
@Override
public KEY_TYPE set(int index, KEY_TYPE element) {
ReentrantLock lock = list.lock;
lock.lock();
try {
checkSubRange(index);
return list.set(offset+index, element);
return list.set(parentOffset+index, element);
}
finally {
lock.unlock();
@@ -1646,11 +1663,18 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public KEY_TYPE swapRemove(int index) {
ReentrantLock lock = list.lock;
if(index < 0 || index >= size) throw new IndexOutOfBoundsException();
ReentrantLock lock = this.lock;
lock.lock();
try {
checkSubRange(index);
KEY_TYPE result = list.swapRemove(index+parentOffset);
KEY_TYPE[] data = getter.get();
KEY_TYPE result = data[offset+index];
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length-1);
int end = offset+size-1;
System.arraycopy(data, 0, newElements, 0, end);
if(end != newElements.length) System.arraycopy(data, end+1, newElements, end, data.length-end-1);
if(index+offset != end) newElements[index+offset] = data[end];
setter.accept(newElements);
size--;
return result;
}
@@ -1661,7 +1685,6 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public KEY_TYPE REMOVE(int index) {
ReentrantLock lock = list.lock;
lock.lock();
try {
checkSubRange(index);
@@ -1674,6 +1697,371 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
}
}
#if !TYPE_OBJECT
@Override
public boolean REMOVE_KEY(KEY_TYPE type) {
int index = indexOf(type);
if(index == -1) return false;
REMOVE(index);
return true;
}
#else
@Override
public boolean remove(Object type) {
int index = indexOf(type);
if(index == -1) return false;
REMOVE(index);
return true;
}
#endif
#if TYPE_OBJECT
@Override
public void sort(Comparator<? super CLASS_TYPE> c) {
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newData = Arrays.copyOf(data, data.length);
if(c != null) ARRAYS.stableSort(newData, offset, offset+size, c);
else ARRAYS.stableSort(newData, offset, offset+size);
setter.accept(newData);
}
finally {
lock.unlock();
}
}
@Override
public void unstableSort(Comparator<? super CLASS_TYPE> c) {
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newData = Arrays.copyOf(data, data.length);
if(c != null) ARRAYS.unstableSort(newData, offset, offset+size, c);
else ARRAYS.unstableSort(newData, offset, offset+size);
setter.accept(newData);
}
finally {
lock.unlock();
}
}
#else
@Override
public void sort(COMPARATOR c) {
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newData = Arrays.copyOf(data, data.length);
if(c != null) ARRAYS.stableSort(newData, offset, offset+size, c);
else ARRAYS.stableSort(newData, offset, offset+size);
setter.accept(newData);
}
finally {
lock.unlock();
}
}
@Override
public void unstableSort(COMPARATOR c) {
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newData = Arrays.copyOf(data, data.length);
if(c != null) ARRAYS.unstableSort(newData, offset, offset+size, c);
else ARRAYS.unstableSort(newData, offset, offset+size);
setter.accept(newData);
}
finally {
lock.unlock();
}
}
#endif
@Override
@Deprecated
public boolean removeAll(Collection<?> c) {
if(c.isEmpty()) return false;
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length);
int j = 0;
for(int i= 0,m=data.length;i<m;i++) {
if(i < offset || i >= offset+size) newElements[j++] = data[i];
else if(!c.contains(KEY_TO_OBJ(data[i]))) newElements[j++] = data[i];
}
if(data.length != j) {
setter.accept(Arrays.copyOf(newElements, j));
size -= data.length - j;
return true;
}
return false;
}
finally {
lock.unlock();
}
}
@Override
@Deprecated
public boolean retainAll(Collection<?> c) {
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
if(c.isEmpty()) {
if(size > 0) {
clear();
return true;
}
return false;
}
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length);
int j = 0;
for(int i= 0,m=data.length;i<m;i++) {
if(i < offset || i >= offset+size) newElements[j++] = data[i];
else if(c.contains(KEY_TO_OBJ(data[i]))) newElements[j++] = data[i];
}
if(data.length != j) {
setter.accept(Arrays.copyOf(newElements, j));
size -= data.length - j;
return true;
}
return false;
}
finally {
lock.unlock();
}
}
@Override
@Deprecated
public boolean removeIf(Predicate<? super CLASS_TYPE> filter) {
Objects.requireNonNull(filter);
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length);
int j = 0;
for(int i= 0,m=data.length;i<m;i++) {
if(i < offset || i >= offset+size) newElements[j++] = data[i];
else if(!filter.test(KEY_TO_OBJ(data[i]))) newElements[j++] = data[i];
}
if(data.length != j) {
setter.accept(Arrays.copyOf(newElements, j));
size -= data.length - j;
return true;
}
return false;
}
finally {
lock.unlock();
}
}
@Override
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c) {
if(c.isEmpty()) return false;
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length);
int j = 0;
for(int i= 0,m=data.length;i<m;i++) {
if(i < offset || i >= offset+size) newElements[j++] = data[i];
else if(!c.contains(data[i])) newElements[j++] = data[i];
}
if(data.length != j) {
setter.accept(Arrays.copyOf(newElements, j));
size -= data.length - j;
return true;
}
return false;
}
finally {
lock.unlock();
}
}
@Override
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c, CONSUMER KEY_GENERIC_TYPE r) {
if(c.isEmpty()) return false;
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length);
int j = 0;
for(int i= 0,m=data.length;i<m;i++) {
if(i < offset || i >= offset+size) newElements[j++] = data[i];
else if(!c.contains(data[i])) newElements[j++] = data[i];
else r.accept(data[i]);
}
if(data.length != j) {
setter.accept(Arrays.copyOf(newElements, j));
size -= data.length - j;
return true;
}
return false;
}
finally {
lock.unlock();
}
}
@Override
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c) {
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
if(c.isEmpty()) {
if(size > 0) {
clear();
return true;
}
return false;
}
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length);
int j = 0;
for(int i= 0,m=data.length;i<m;i++) {
if(i < offset || i >= offset+size) newElements[j++] = data[i];
else if(c.contains(data[i])) newElements[j++] = data[i];
}
if(data.length != j) {
setter.accept(Arrays.copyOf(newElements, j));;
size -= data.length - j;
return true;
}
return false;
}
finally {
lock.unlock();
}
}
@Override
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c, CONSUMER KEY_GENERIC_TYPE r) {
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
if(c.isEmpty()) {
if(size > 0) {
forEach(r);
clear();
return true;
}
return false;
}
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length);
int j = 0;
for(int i= 0,m=data.length;i<m;i++) {
if(i < offset || i >= offset+size) newElements[j++] = data[i];
else if(c.contains(data[i])) newElements[j++] = data[i];
else r.accept(data[i]);
}
if(data.length != j) {
setter.accept(Arrays.copyOf(newElements, j));
size -= data.length - j;
return true;
}
return false;
}
finally {
lock.unlock();
}
}
#if PRIMITIVES
@Override
public boolean remIf(JAVA_PREDICATE filter) {
Objects.requireNonNull(filter);
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newElements = NEW_KEY_ARRAY(data.length);
int j = 0;
for(int i=0,m=data.length;i<m;i++) {
if(i < offset || i >= offset+size) newElements[j++] = data[i];
else if(!filter.test(data[i])) newElements[j++] = data[i];
}
if(data.length != j) {
setter.accept(Arrays.copyOf(newElements, j));
size -= data.length - j;
return true;
}
return false;
}
finally {
lock.unlock();
}
}
#endif
@Override
@Primitive
public void replaceAll(UnaryOperator<CLASS_TYPE> o) {
#if PRIMITIVES
Objects.requireNonNull(o);
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
REPLACE(T -> OBJ_TO_KEY(o.apply(KEY_TO_OBJ(SanityChecks.SANITY_CAST(T)))));
#else
REPLACE(T -> OBJ_TO_KEY(o.apply(KEY_TO_OBJ(T))));
#endif
#else
Objects.requireNonNull(o);
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newData = Arrays.copyOf(data, data.length);
for(int i = 0,m=size;i<m;i++)
newData[i+offset] = OBJ_TO_KEY(o.apply(KEY_TO_OBJ(newData[i+offset])));
setter.accept(newData);
}
finally {
lock.unlock();
}
#endif
}
#if PRIMITIVES
@Override
public void REPLACE(JAVA_UNARY_OPERATOR o) {
Objects.requireNonNull(o);
ReentrantLock lock = this.lock;
lock.lock();
try {
KEY_TYPE[] data = getter.get();
KEY_TYPE[] newData = Arrays.copyOf(data, data.length);
for(int i = 0,m=size;i<m;i++)
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
newData[i+offset] = SanityChecks.SANITY_CAST(o.APPLY_CAST(newData[i+offset]));
#else
newData[i+offset] = o.APPLY(newData[i+offset]);
#endif
setter.accept(newData);
}
finally {
lock.unlock();
}
}
#endif
@Override
public int size() {
return size;
@@ -1682,10 +2070,9 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public void clear() {
if(size == 0) return;
ReentrantLock lock = list.lock;
lock.lock();
try {
list.removeElements(offset, offset+size);
list.removeElements(parentOffset, parentOffset+size);
size = 0;
}
finally {
@@ -1705,7 +2092,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@Override
public LIST KEY_GENERIC_TYPE subList(int fromIndex, int toIndex) {
SanityChecks.checkArrayCapacity(size, fromIndex, toIndex-fromIndex);
return new COWSubListBRACES(list, offset, fromIndex, toIndex);
return new COWSubListBRACES(this, lock, setter, getter, offset, fromIndex, toIndex);
}
protected void checkSubRange(int index) {
@@ -1773,7 +2160,7 @@ public class COPY_ON_WRITE_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENER
@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);
int steps = Math.min(amount, list.size() - index);
index += steps;
return steps;
}
@@ -183,36 +183,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) {
int length = c.size();
if(length == 0) return false;
checkAddRange(index);
Entry KEY_GENERIC_TYPE next;
Entry KEY_GENERIC_TYPE prev;
if(index == size) {
prev = last;
next = null;
}
else if(index == 0) {
next = first;
prev = null;
}
else {
next = getNode(index);
prev = next.prev;
}
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();) {
Entry KEY_GENERIC_TYPE entry = new EntryBRACES(iter.NEXT(), prev, null);
if(prev == null) first = entry;
else prev.next = entry;
prev = entry;
}
if(next == null) last = prev;
else {
prev.next = next;
next.prev = prev;
}
size += length;
return true;
return addAll(index, (COLLECTION KEY_GENERIC_TYPE)c); //
}
@Override
@@ -322,13 +293,13 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public KEY_TYPE first() {
if(first == null) throw new IllegalStateException();
if(first == null) throw new NoSuchElementException();
return first.value;
}
@Override
public KEY_TYPE last() {
if(last == null) throw new IllegalStateException();
if(last == null) throw new NoSuchElementException();
return last.value;
}
@@ -561,13 +532,13 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
@Override
public KEY_TYPE dequeue() {
if(first == null) throw new IllegalStateException();
if(first == null) throw new NoSuchElementException();
return unlinkFirst(first);
}
@Override
public KEY_TYPE dequeueLast() {
if(last == null) throw new IllegalStateException();
if(last == null) throw new NoSuchElementException();
return unlinkLast(last);
}
@@ -625,6 +596,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
temp.next = before.next;
temp.prev = before;
before.next = temp;
temp.next.prev = temp;
}
return result;
}
@@ -657,6 +629,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
temp.next = before.next;
temp.prev = before;
before.next = temp;
temp.next.prev = temp;
}
return true;
}
@@ -707,7 +680,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
}
return;
}
Entry KEY_GENERIC_TYPE entry = getNode(to);
Entry KEY_GENERIC_TYPE entry = getNode(to-1);
while(length > 0) {
Entry KEY_GENERIC_TYPE prev = entry.prev;
unlink(entry);
@@ -733,7 +706,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
}
return a;
}
Entry KEY_GENERIC_TYPE entry = getNode(to);
Entry KEY_GENERIC_TYPE entry = getNode(to-1);
for(int i = length-1;length > 0;i--, length--) {
Entry KEY_GENERIC_TYPE prev = entry.prev;
a[i] = (K)unlink(entry);
@@ -759,7 +732,7 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
}
return d;
}
Entry KEY_GENERIC_TYPE entry = getNode(to);
Entry KEY_GENERIC_TYPE entry = getNode(to-1);
for(int i = length-1;length > 0;i--, length--) {
Entry KEY_GENERIC_TYPE prev = entry.prev;
d[i] = unlink(entry);
@@ -1141,6 +1114,11 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
this.prev = prev;
this.next = next;
}
@Override
public String toString() {
return KEY_TO_STRING(value);
}
}
private class ListIter implements LIST_ITERATOR KEY_GENERIC_TYPE
@@ -285,6 +285,16 @@ public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap<CL
}
#endif
@Override
public CLASS_VALUE_TYPE remove(Object key) {
#if TYPE_OBJECT
return VALUE_TO_OBJ(REMOVE_VALUE((CLASS_TYPE)key));
#else
return key instanceof CLASS_TYPE ? VALUE_TO_OBJ(REMOVE_VALUE(CLASS_TO_KEY(key))) : VALUE_TO_OBJ(getDefaultReturnValue());
#endif
}
@Override
public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
Objects.requireNonNull(action);
@@ -306,7 +316,11 @@ public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap<CL
#else
@Override
public boolean remove(Object o) {
return VALUE_EQUALS_NOT(ABSTRACT_MAP.this.remove(o), getDefaultReturnValue());
if(ABSTRACT_MAP.this.containsKey(o)) {
ABSTRACT_MAP.this.remove(o);
return true;
}
return false;
}
#endif
@@ -73,6 +73,7 @@ import speiger.src.collections.objects.collections.ObjectBidirectionalIterator;
import speiger.src.collections.objects.sets.AbstractObjectSet;
import speiger.src.collections.objects.sets.ObjectSet;
import speiger.src.collections.utils.HashUtil;
import speiger.src.collections.utils.ITrimmable;
/**
* A TypeSpecific ConcurrentHashMap implementation that is based on <a href="https://github.com/google/guava">Guavas</a> approach and backing array implementations.
@@ -84,7 +85,7 @@ import speiger.src.collections.utils.HashUtil;
* @Type(T)
* @ValueType(V)
*/
public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE
public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE, ITrimmable
{
/** Segment Limit */
private static final int MAX_SEGMENTS = 1 << 16;
@@ -538,6 +539,30 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
}
}
@Override
public boolean trim(int size) {
int segmentCapacity = size / segments.length;
if(segmentCapacity * segments.length < size) {
segmentCapacity++;
}
boolean result = false;
for(int i = 0, m=segments.length;i<m;i++) {
result |= segments[i].trim(segmentCapacity);
}
return result;
}
@Override
public void clearAndTrim(int size) {
int segmentCapacity = size / segments.length;
if(segmentCapacity * segments.length < size) {
segmentCapacity++;
}
for(int i = 0, m=segments.length;i<m;i++) {
segments[i].clearAndTrim(segmentCapacity);
}
}
@Override
public boolean isEmpty() {
for(int i = 0,m=segments.length;i<m;i++) {
@@ -2025,7 +2050,11 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
long stamp = writeLock();
try
{
#if TYPE_OBJECT
if(key == null) {
#else
if(key == null || (key instanceof CLASS_TYPE && KEY_EQUALS_NULL(CLASS_TO_KEY(key)))) {
#endif
if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
removeNullIndex();
return true;
@@ -2202,7 +2231,7 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
protected boolean trim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size || this.size > Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
if(request >= mask+1 || this.size > Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
long stamp = writeLock();
try {
try {
@@ -2218,7 +2247,7 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
protected void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= mask+1) {
clear();
return;
}
@@ -2298,6 +2327,9 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
#endif
protected int findIndex(int hash, Object key) {
if(key == null) return containsNull ? nullIndex : -(nullIndex + 1);
#if !TYPE_OBJECT
if(KEY_EQUALS_NULL(CLASS_TO_KEY(key))) return containsNull ? nullIndex : -(nullIndex + 1);
#endif
int pos = hash & mask;
KEY_TYPE current = keys[pos];
if(KEY_EQUALS_NOT_NULL(current)) {
@@ -369,8 +369,7 @@ public class LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends CUSTOM_HASH_M
public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
if(size == 0) throw new NoSuchElementException();
int pos = firstIndex;
firstIndex = (int)links[pos];
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
onNodeRemoved(pos);
KEY_TYPE result = keys[pos];
size--;
if(strategy.equals(result, EMPTY_KEY_VALUE)) {
@@ -393,8 +392,7 @@ public class LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends CUSTOM_HASH_M
public KEY_TYPE POLL_LAST_ENTRY_KEY() {
if(size == 0) throw new NoSuchElementException();
int pos = lastIndex;
lastIndex = (int)(links[pos] >>> 32);
if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL;
onNodeRemoved(pos);
KEY_TYPE result = keys[pos];
size--;
if(strategy.equals(result, EMPTY_KEY_VALUE)) {
@@ -455,7 +453,7 @@ public class LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends CUSTOM_HASH_M
@Override
public void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= nullIndex) {
clear();
return;
}
@@ -394,7 +394,11 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
@Override
public boolean remove(Object key, Object value) {
Objects.requireNonNull(value);
#if TYPE_OBJECT
if(key == null) {
#else
if(key == null || (key instanceof CLASS_TYPE && strategy.equals(CLASS_TO_KEY(key), EMPTY_KEY_VALUE))) {
#endif
if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
removeNullIndex();
return true;
@@ -628,7 +632,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
@Override
public boolean trim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size || this.size > Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
if(request >= nullIndex || this.size > Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
try {
rehash(request);
}
@@ -639,7 +643,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
@Override
public void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= nullIndex) {
clear();
return;
}
@@ -669,6 +673,9 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
protected int findIndex(CLASS_TYPE key) {
if(key == null) return containsNull ? nullIndex : -(nullIndex + 1);
KEY_TYPE keyType = CLASS_TO_KEY(key);
#if !TYPE_OBJECT
if(strategy.equals(keyType, EMPTY_KEY_VALUE)) return containsNull ? nullIndex : -(nullIndex + 1);
#endif
int pos = HashUtil.mix(strategy.hashCode(keyType)) & mask;
KEY_TYPE current = keys[pos];
if(!strategy.equals(current, EMPTY_KEY_VALUE)) {
@@ -373,8 +373,7 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G
public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
if(size == 0) throw new NoSuchElementException();
int pos = firstIndex;
firstIndex = (int)links[pos];
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
onNodeRemoved(pos);
KEY_TYPE result = keys[pos];
size--;
if(KEY_EQUALS_NULL(result)) {
@@ -397,8 +396,7 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G
public KEY_TYPE POLL_LAST_ENTRY_KEY() {
if(size == 0) throw new NoSuchElementException();
int pos = lastIndex;
lastIndex = (int)(links[pos] >>> 32);
if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL;
onNodeRemoved(pos);
KEY_TYPE result = keys[pos];
size--;
if(KEY_EQUALS_NULL(result)) {
@@ -459,7 +457,7 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G
@Override
public void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= nullIndex) {
clear();
return;
}
@@ -362,7 +362,11 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
@Override
public boolean remove(Object key, Object value) {
Objects.requireNonNull(value);
#if TYPE_OBJECT
if(key == null) {
#else
if(key == null || (key instanceof CLASS_TYPE && KEY_EQUALS_NULL(CLASS_TO_KEY(key)))) {
#endif
if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
removeNullIndex();
return true;
@@ -589,7 +593,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
@Override
public boolean trim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size || this.size > Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
if(request >= nullIndex || this.size >= Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
try {
rehash(request);
}
@@ -600,7 +604,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
@Override
public void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= nullIndex) {
clear();
return;
}
@@ -629,6 +633,9 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
#endif
protected int findIndex(Object key) {
if(key == null) return containsNull ? nullIndex : -(nullIndex + 1);
#if !TYPE_OBJECT
if(key instanceof CLASS_TYPE && KEY_EQUALS_NULL(CLASS_TO_KEY(key))) return containsNull ? nullIndex : -(nullIndex + 1);
#endif
int pos = HashUtil.mix(key.hashCode()) & mask;
KEY_TYPE current = keys[pos];
if(KEY_EQUALS_NOT_NULL(current)) {
@@ -517,6 +517,9 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
#endif
protected int findIndex(Object key) {
if(key == null) return containsNull ? nullIndex : -(nullIndex + 1);
#if !TYPE_OBJECT
if(KEY_EQUALS_NULL(CLASS_TO_KEY(key))) return containsNull ? nullIndex : -(nullIndex + 1);
#endif
int pos = HashUtil.mix(key.hashCode()) & mask;
KEY_TYPE current = keys[pos];
if(KEY_EQUALS_NOT_NULL(current)) {
@@ -1233,6 +1233,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
public EntryIterator() {}
public EntryIterator(KEY_TYPE from) {
index = findIndex(from);
if(index == -1) throw new NoSuchElementException();
}
@Override
@@ -1263,6 +1264,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
public KeyIterator() {}
public KeyIterator(KEY_TYPE element) {
index = findIndex(element);
if(index == -1) throw new NoSuchElementException();
}
@Override
@@ -4,6 +4,7 @@ import java.util.Arrays;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
@@ -76,8 +77,8 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
if(keys.length != values.length) throw new IllegalArgumentException("Keys and Values have to be the same size");
keyType = keys[0].getDeclaringClass();
this.keys = getKeyUniverse(keyType);
this.values = NEW_VALUE_ARRAY(keys.length);
present = new long[((keys.length - 1) >> 6) + 1];
this.values = NEW_VALUE_ARRAY(this.keys.length);
present = new long[((this.keys.length - 1) >> 6) + 1];
putAll(keys, values);
}
@@ -93,8 +94,8 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
if(keys.length != values.length) throw new IllegalArgumentException("Keys and Values have to be the same size");
keyType = keys[0].getDeclaringClass();
this.keys = getKeyUniverse(keyType);
this.values = NEW_VALUE_ARRAY(keys.length);
present = new long[((keys.length - 1) >> 6) + 1];
this.values = NEW_VALUE_ARRAY(this.keys.length);
present = new long[((this.keys.length - 1) >> 6) + 1];
putAll(keys, values);
}
@@ -530,6 +531,14 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
return false;
}
@Override
public void forEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
if(size() <= 0) return;
for(int i = 0,m=keys.length;i<m;i++) {
if(isSet(i)) action.accept(new BasicEntryKV_BRACES(keys[i], values[i]));
}
}
@Override
public ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iterator() {
return new EntryIterator();
@@ -66,9 +66,9 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
if(keys.length != values.length) throw new IllegalArgumentException("Keys and Values have to be the same size");
keyType = keys[0].getDeclaringClass();
this.keys = getKeyUniverse(keyType);
this.values = NEW_VALUE_ARRAY(keys.length);
present = new long[((keys.length - 1) >> 6) + 1];
links = new long[keys.length];
this.values = NEW_VALUE_ARRAY(this.keys.length);
present = new long[((this.keys.length - 1) >> 6) + 1];
links = new long[this.keys.length];
putAll(keys, values);
}
@@ -84,9 +84,9 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
if(keys.length != values.length) throw new IllegalArgumentException("Keys and Values have to be the same size");
keyType = keys[0].getDeclaringClass();
this.keys = getKeyUniverse(keyType);
this.values = NEW_VALUE_ARRAY(keys.length);
present = new long[((keys.length - 1) >> 6) + 1];
links = new long[keys.length];
this.values = NEW_VALUE_ARRAY(this.keys.length);
present = new long[((this.keys.length - 1) >> 6) + 1];
links = new long[this.keys.length];
putAll(keys, values);
}
@@ -239,7 +239,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
@Override
public VALUE_TYPE getAndMoveToFirst(T key) {
int index = key.ordinal();
if(index < 0) return getDefaultReturnValue();
if(!isSet(index)) return getDefaultReturnValue();
moveToFirstIndex(index);
return values[index];
}
@@ -247,7 +247,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
@Override
public VALUE_TYPE getAndMoveToLast(T key) {
int index = key.ordinal();
if(index < 0) return getDefaultReturnValue();
if(!isSet(index)) return getDefaultReturnValue();
moveToLastIndex(index);
return values[index];
}
@@ -828,6 +828,7 @@ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VA
previous = from.ordinal() - 1;
index = from.ordinal();
next = from.ordinal();
if(!isSet(index)) throw new NoSuchElementException();
}
public boolean hasNext() {
@@ -1578,13 +1578,15 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
@Override
public VALUE_TYPE FIRST_ENTRY_VALUE() {
Node KEY_VALUE_GENERIC_TYPE entry = subLowest();
return entry == null ? map.getDefaultReturnValue() : entry.value;
if(entry == null) throw new NoSuchElementException();
return entry.value;
}
@Override
public VALUE_TYPE LAST_ENTRY_VALUE() {
Node KEY_VALUE_GENERIC_TYPE entry = subHighest();
return entry == null ? map.getDefaultReturnValue() : entry.value;
if(entry == null) throw new NoSuchElementException();
return entry.value;
}
@Override
@@ -1645,13 +1645,15 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
@Override
public VALUE_TYPE FIRST_ENTRY_VALUE() {
Node KEY_VALUE_GENERIC_TYPE entry = subLowest();
return entry == null ? map.getDefaultReturnValue() : entry.value;
if(entry == null) throw new NoSuchElementException();
return entry.value;
}
@Override
public VALUE_TYPE LAST_ENTRY_VALUE() {
Node KEY_VALUE_GENERIC_TYPE entry = subHighest();
return entry == null ? map.getDefaultReturnValue() : entry.value;
if(entry == null) throw new NoSuchElementException();
return entry.value;
}
@Override
@@ -557,8 +557,8 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
*/
public KEY_TYPE ENTRY_KEY();
public default CLASS_TYPE getKey() { return KEY_TO_OBJ(ENTRY_KEY()); }
#endif
#endif
#if !VALUE_OBJECT
/**
* Type Specific getValue method that reduces boxing/unboxing
@@ -1381,6 +1381,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
* @param initialSize the requested start capacity
*/
public BuilderCache(int initialSize) {
if(initialSize < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed");
keys = NEW_KEY_ARRAY(initialSize);
values = NEW_VALUE_ARRAY(initialSize);
}
@@ -888,15 +888,11 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
@Override
public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; }
public KEY_TYPE getDefaultMaxValue() { return super.getDefaultMinValue(); }
public KEY_TYPE getDefaultMinValue() { return super.getDefaultMaxValue(); }
@Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) {
if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement out of range");
if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement out of range");
return new DescendingSubSetBRACES(set, false, fromElement, fromInclusive, false, toElement, toInclusive);
return new DescendingSubSetBRACES(set, false, toElement, toInclusive, false, fromElement, fromInclusive);
}
@Override
@@ -973,21 +969,15 @@ public class AVL_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
#if !TYPE_OBJECT
@Override
public void setDefaultMaxValue(KEY_TYPE value) { set.setDefaultMaxValue(value); }
@Override
public KEY_TYPE getDefaultMaxValue() { return set.getDefaultMaxValue(); }
@Override
public void setDefaultMinValue(KEY_TYPE value) { set.setDefaultMinValue(value); }
@Override
public KEY_TYPE getDefaultMinValue() { return set.getDefaultMinValue(); }
#else
public KEY_TYPE getDefaultMaxValue() { return null; }
public KEY_TYPE getDefaultMinValue() { return null; }
#endif
@Override
public abstract BI_ITERATOR KEY_GENERIC_TYPE iterator();
@@ -54,6 +54,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
* @throws NegativeArraySizeException if the capacity is negative
*/
public ARRAY_SET(int capacity) {
if(capacity < 0) throw new IllegalStateException("Size has to be 0 or greater");
data = NEW_KEY_ARRAY(capacity);
}
@@ -168,7 +169,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
}
else if(index != size - 1) {
o = data[index];
System.arraycopy(data, index+1, data, index, size - index);
System.arraycopy(data, index+1, data, index, size - index - 1);
data[size-1] = o;
}
return false;
@@ -554,348 +555,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
if (a.length > size) a[size] = null;
return a;
}
// Disabled until a Proper Implementation can be thought out or it is decided that the interface is thrown out.
// private class SubSet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
// int offset;
// int length;
//
// SubSet(int offset, int length) {
// this.offset = offset;
// this.length = length;
// }
//
// int end() { return offset+length; }
//
// @Override
// public boolean add(KEY_TYPE o) {
// int index = findIndex(o);
// if(index == -1) {
// if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
// if(end() != size) System.arraycopy(data, end(), data, end()+1, size-(offset+length));
// data[end()] = o;
// size++;
// length++;
// return true;
// }
// return false;
// }
//
// @Override
// public boolean addAndMoveToFirst(KEY_TYPE o) {
// int index = findIndex(o);
// if(index == -1) {
// if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
// System.arraycopy(data, offset, data, offset+1, size-offset);
// data[offset] = o;
// size++;
// length++;
// return true;
// }
// else if(index != 0) {
// o = data[index];
// System.arraycopy(data, offset, data, offset+1, index-offset);
// data[offset] = o;
// }
// return false;
// }
//
// @Override
// public boolean addAndMoveToLast(KEY_TYPE o) {
// int index = findIndex(o);
// if(index == -1) {
// if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
// System.arraycopy(data, end()+1, data, end(), size-end());
// data[end()] = o;
// size++;
// length++;
// return true;
// }
// else if(index != 0) {
// o = data[index];
// System.arraycopy(data, offset+1, data, offset, index-offset);
// data[offset+length] = o;
// }
// return false;
// }
//
// @Override
// public boolean moveToFirst(KEY_TYPE o) {
// int index = findIndex(o);
// if(index > offset) {
// o = data[index];
// System.arraycopy(data, offset, data, offset+1, index-offset);
// data[offset] = o;
// return true;
// }
// return false;
// }
//
// @Override
// public boolean moveToLast(KEY_TYPE o) {
// int index = findIndex(o);
// if(index != -1 && index < end()-1) {
// o = data[index];
// System.arraycopy(data, index+1, data, index, end()-index-1);
// data[end()-1] = o;
// return true;
// }
// return false;
// }
//
//#if !TYPE_OBJECT
// @Override
// public boolean contains(KEY_TYPE e) {
// return findIndex(e) != -1;
// }
//
//#endif
// @Override
// public boolean contains(Object e) {
// return findIndex(e) != -1;
// }
//
// @Override
// public KEY_TYPE FIRST_KEY() {
// if(length == 0) throw new NoSuchElementException();
// return data[offset];
// }
//
// @Override
// public KEY_TYPE LAST_KEY() {
// if(length == 0) throw new NoSuchElementException();
// return data[end()-1];
// }
//
//#if !TYPE_OBJECT
// @Override
// public boolean remove(KEY_TYPE o) {
// int index = findIndex(o);
// if(index != -1) {
// size--;
// length--;
// if(index != size) System.arraycopy(data, index+1, data, index, size - index);
// return true;
// }
// return false;
// }
//
//#endif
// @Override
// public boolean remove(Object o) {
// int index = findIndex(o);
// if(index != -1) {
// size--;
// length--;
// if(index != size) System.arraycopy(data, index+1, data, index, size - index);
//#if TYPE_OBJECT
// data[size] = EMPTY_KEY_VALUE;
//#endif
// return true;
// }
// return false;
// }
//
// @Override
// public KEY_TYPE POLL_FIRST_KEY() {
// if(length == 0) throw new NoSuchElementException();
// size--;
// length--;
// KEY_TYPE result = data[offset];
// System.arraycopy(data, offset+1, data, offset, size-offset);
//#if TYPE_OBJECT
// data[size] = EMPTY_KEY_VALUE;
//#endif
// return result;
// }
//
// @Override
// public KEY_TYPE POLL_LAST_KEY() {
// if(length == 0) throw new NoSuchElementException();
// KEY_TYPE result = data[offset+length];
// size--;
// length--;
// System.arraycopy(data, end()+1, data, end(), size-end());
//#if TYPE_OBJECT
// data[size] = EMPTY_KEY_VALUE;
//#endif
// return result;
// }
//
// @Override
// public COMPARATOR KEY_GENERIC_TYPE comparator() {
// return null;
// }
//
// @Override
// public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
// return new SetIterator(offset);
// }
//
// @Override
// public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
// int index = findIndex(fromElement);
// if(index != -1) return new SetIterator(index);
// throw new NoSuchElementException();
// }
//
// @Override
// public SubSet copy() { throw new UnsupportedOperationException(); }
//
// @Override
// public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) {
// int fromIndex = findIndex(fromElement);
// int toIndex = findIndex(toElement);
// if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException();
// return new SubSet(fromIndex, toIndex - fromIndex + 1);
// }
//
// @Override
// public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) {
// int toIndex = findIndex(toElement);
// if(toIndex == -1) throw new NoSuchElementException();
// return new SubSet(0, toIndex+1);
// }
//
// @Override
// public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) {
// int fromIndex = findIndex(fromElement);
// if(fromIndex == -1) throw new NoSuchElementException();
// return new SubSet(fromIndex, size - fromIndex);
// }
//
// @Override
// public int size() {
// return length;
// }
//
//#if !TYPE_OBJECT
// @Override
// public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
// if(a == null || a.length < size()) return Arrays.copyOfRange(data, offset, end());
// System.arraycopy(data, offset, a, 0, size());
// return a;
// }
//
//#endif
// @Override
// @Deprecated
// public Object[] toArray() {
// Object[] obj = new Object[size()];
// for(int i = 0;i<size();i++)
// obj[i] = KEY_TO_OBJ(data[offset+i]);
// return obj;
// }
//
// @Override
// @Primitive
// public <E> E[] toArray(E[] a) {
// if(a == null) a = (E[])new Object[size()];
// 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[offset+i]);
// return a;
// }
//
//#if !TYPE_OBJECT
// protected int findIndex(KEY_TYPE o) {
// for(int i = length-1;i>=0;i--)
// if(KEY_EQUALS(data[offset+i], o)) return i + offset;
// return -1;
// }
//
//#endif
// protected int findIndex(Object o) {
// for(int i = length-1;i>=0;i--)
// if(EQUALS_KEY_TYPE(data[offset+i], o)) return i + offset;
// return -1;
// }
//
// private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
// int index;
// int lastReturned = -1;
//
// public SetIterator(int index) {
// this.index = index;
// }
//
// @Override
// public boolean hasNext() {
// return index < size();
// }
//
// @Override
// public KEY_TYPE NEXT() {
// if(!hasNext()) throw new NoSuchElementException();
// lastReturned = index;
// return data[index++];
// }
//
// @Override
// public boolean hasPrevious() {
// return index > 0;
// }
//
// @Override
// public KEY_TYPE PREVIOUS() {
// if(!hasPrevious()) throw new NoSuchElementException();
// lastReturned = index;
// return data[index--];
// }
//
// @Override
// public int nextIndex() {
// return index;
// }
//
// @Override
// public int previousIndex() {
// return index-1;
// }
//
// @Override
// public void remove() {
// if(lastReturned == -1)
// throw new IllegalStateException();
// SubSet.this.remove(data[lastReturned]);
// if(lastReturned < index)
// index--;
// lastReturned = -1;
// }
//
// #if TYPE_OBJECT
// @Override
// public void set(Object e) { throw new UnsupportedOperationException(); }
//
// @Override
// public void add(Object e) { throw new UnsupportedOperationException(); }
//
// #else
// @Override
// public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
//
// @Override
// public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
//
// #endif
// @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;
// }
// }
// }
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
int index;
int lastReturned = -1;
@@ -510,6 +510,7 @@ public class IMMUTABLE_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERI
next = (int)(links[current]);
result++;
}
if(index >= 0) index+=result;
return result;
}
@@ -521,6 +522,7 @@ public class IMMUTABLE_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERI
previous = (int)(links[current] >> 32);
result++;
}
if(index >= 0) index-=result;
return result;
}
@@ -123,7 +123,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
* @throws IllegalStateException if offset and length causes to step outside of the arrays range
*/
public LINKED_CUSTOM_HASH_SET(KEY_TYPE[] array, int offset, int length, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
this(length < 0 ? 0 : length, strategy);
this(length, strategy);
SanityChecks.checkArrayCapacity(array.length, offset, length);
for(int i = 0;i<length;i++) add(array[offset+i]);
}
@@ -284,7 +284,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
@Override
public boolean moveToFirst(KEY_TYPE o) {
if(strategy.equals(FIRST_KEY(), o)) return false;
if(isEmpty() || strategy.equals(FIRST_KEY(), o)) return false;
if(strategy.equals(o, EMPTY_KEY_VALUE)) {
if(containsNull) {
moveToFirstIndex(nullIndex);
@@ -306,7 +306,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
@Override
public boolean moveToLast(KEY_TYPE o) {
if(strategy.equals(LAST_KEY(), o)) return false;
if(isEmpty() || strategy.equals(LAST_KEY(), o)) return false;
if(strategy.equals(o, EMPTY_KEY_VALUE)) {
if(containsNull) {
moveToLastIndex(nullIndex);
@@ -372,8 +372,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
public KEY_TYPE POLL_FIRST_KEY() {
if(size == 0) throw new NoSuchElementException();
int pos = firstIndex;
firstIndex = (int)links[pos];
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
onNodeRemoved(pos);
KEY_TYPE result = keys[pos];
size--;
if(strategy.equals(result, EMPTY_KEY_VALUE)) {
@@ -395,8 +394,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
public KEY_TYPE POLL_LAST_KEY() {
if(size == 0) throw new NoSuchElementException();
int pos = lastIndex;
lastIndex = (int)(links[pos] >>> 32);
if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL;
onNodeRemoved(pos);
KEY_TYPE result = keys[pos];
size--;
if(strategy.equals(result, EMPTY_KEY_VALUE)) {
@@ -510,7 +508,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
@Override
public void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= nullIndex) {
clear();
return;
}
@@ -725,6 +723,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
next = (int)(links[current]);
result++;
}
if(index >= 0) index+=result;
return result;
}
@@ -736,6 +735,7 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
previous = (int)(links[current] >> 32);
result++;
}
if(index >= 0) index-=result;
return result;
}
@@ -110,7 +110,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
* @throws IllegalStateException if offset and length causes to step outside of the arrays range
*/
public LINKED_HASH_SET(KEY_TYPE[] array, int offset, int length, float loadFactor) {
this(length < 0 ? 0 : length);
this(length);
SanityChecks.checkArrayCapacity(array.length, offset, length);
for(int i = 0;i<length;i++) add(array[offset+i]);
}
@@ -255,7 +255,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
@Override
public boolean moveToFirst(KEY_TYPE o) {
if(KEY_EQUALS(FIRST_KEY(), o)) return false;
if(isEmpty() || KEY_EQUALS(FIRST_KEY(), o)) return false;
if(KEY_EQUALS_NULL(o)) {
if(containsNull) {
moveToFirstIndex(nullIndex);
@@ -277,7 +277,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
@Override
public boolean moveToLast(KEY_TYPE o) {
if(KEY_EQUALS(LAST_KEY(), o)) return false;
if(isEmpty() || KEY_EQUALS(LAST_KEY(), o)) return false;
if(KEY_EQUALS_NULL(o)) {
if(containsNull) {
moveToLastIndex(nullIndex);
@@ -343,8 +343,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
public KEY_TYPE POLL_FIRST_KEY() {
if(size == 0) throw new NoSuchElementException();
int pos = firstIndex;
firstIndex = (int)links[pos];
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
onNodeRemoved(pos);
KEY_TYPE result = keys[pos];
size--;
if(KEY_EQUALS_NULL(result)) {
@@ -366,8 +365,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
public KEY_TYPE POLL_LAST_KEY() {
if(size == 0) throw new NoSuchElementException();
int pos = lastIndex;
lastIndex = (int)(links[pos] >>> 32);
if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL;
onNodeRemoved(pos);
KEY_TYPE result = keys[pos];
size--;
if(KEY_EQUALS_NULL(result)) {
@@ -601,7 +599,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
@Override
public void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= nullIndex) {
clear();
return;
}
@@ -686,6 +684,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
next = (int)(links[current]);
result++;
}
if(index >= 0) index+=result;
return result;
}
@@ -697,6 +696,7 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
previous = (int)(links[current] >> 32);
result++;
}
if(index >= 0) index-=result;
return result;
}
@@ -373,10 +373,10 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
#endif
@Override
public boolean trim(int size) {
int newSize = HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor));
if(newSize >= nullIndex || size >= Math.min((int)Math.ceil(newSize * loadFactor), newSize - 1)) return false;
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= nullIndex || this.size >= Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
try {
rehash(newSize);
rehash(request);
}
catch(OutOfMemoryError e) { return false; }
return true;
@@ -385,7 +385,7 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
@Override
public void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= nullIndex) {
clear();
return;
}
@@ -340,10 +340,10 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
#endif
@Override
public boolean trim(int size) {
int newSize = HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor));
if(newSize >= nullIndex || size >= Math.min((int)Math.ceil(newSize * loadFactor), newSize - 1)) return false;
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= nullIndex || this.size >= Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
try {
rehash(newSize);
rehash(request);
}
catch(OutOfMemoryError e) { return false; }
return true;
@@ -352,7 +352,7 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp
@Override
public void clearAndTrim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size) {
if(request >= nullIndex) {
clear();
return;
}
@@ -949,15 +949,11 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
@Override
public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; }
public KEY_TYPE getDefaultMaxValue() { return super.getDefaultMinValue(); }
public KEY_TYPE getDefaultMinValue() { return super.getDefaultMaxValue(); }
@Override
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) {
if(!inRange(fromElement, fromInclusive)) throw new IllegalArgumentException("fromElement out of range");
if(!inRange(toElement, toInclusive)) throw new IllegalArgumentException("toElement out of range");
return new DescendingSubSetBRACES(set, false, fromElement, fromInclusive, false, toElement, toInclusive);
return new DescendingSubSetBRACES(set, false, toElement, toInclusive, false, fromElement, fromInclusive);
}
@Override
@@ -1034,21 +1030,15 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
#if !TYPE_OBJECT
@Override
public void setDefaultMaxValue(KEY_TYPE value) { set.setDefaultMaxValue(value); }
@Override
public KEY_TYPE getDefaultMaxValue() { return set.getDefaultMaxValue(); }
@Override
public void setDefaultMinValue(KEY_TYPE value) { set.setDefaultMinValue(value); }
@Override
public KEY_TYPE getDefaultMinValue() { return set.getDefaultMinValue(); }
#else
public KEY_TYPE getDefaultMaxValue() { return null; }
public KEY_TYPE getDefaultMinValue() { return null; }
#endif
@Override
public abstract BI_ITERATOR KEY_GENERIC_TYPE iterator();