diff --git a/.classpath b/.classpath
index 8b3d57e..a61782f 100644
--- a/.classpath
+++ b/.classpath
@@ -26,7 +26,7 @@
-
+
diff --git a/build.gradle b/build.gradle
index 0214f4e..1a3c8f7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,15 +6,9 @@ tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
+apply plugin: 'java'
apply plugin: 'eclipse'
-eclipse {
- classpath {
- downloadJavadoc = true
- downloadSources = true
- }
-}
-
repositories {
jcenter()
flatDir {
@@ -22,6 +16,28 @@ repositories {
}
}
+sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'
+
+eclipse {
+ classpath {
+ downloadJavadoc = true
+ downloadSources = true
+ file {
+ whenMerged {
+ //Enforce a custom container and allowing access to the sun.misc package which is nessesary for EnumMaps
+ entries.find{ it.kind == 'con' && it.path.startsWith('org.eclipse.jdt')}.path = 'org.eclipse.jdt.launching.JRE_CONTAINER';
+ }
+ }
+ }
+}
+
+task generateSource(type: JavaExec) {
+ group = 'internal'
+ description = 'Builds the sourcecode'
+ classpath = sourceSets.main.runtimeClasspath
+ main = 'speiger.src.builder.example.TestBuilder'
+}
+
dependencies {
compile 'SimpleCodeGenerator:Simple Code Generator:1.0.1'
testImplementation 'junit:junit:4.12'
diff --git a/libs/Simple Code Generator-1.0.1-sources.jar b/libs/Simple Code Generator-1.0.1-sources.jar
index 9b3630f..60e0673 100644
Binary files a/libs/Simple Code Generator-1.0.1-sources.jar and b/libs/Simple Code Generator-1.0.1-sources.jar differ
diff --git a/libs/Simple Code Generator-1.0.1.jar b/libs/Simple Code Generator-1.0.1.jar
index 952d60d..e6cde34 100644
Binary files a/libs/Simple Code Generator-1.0.1.jar and b/libs/Simple Code Generator-1.0.1.jar differ
diff --git a/src/main/java/speiger/src/builder/example/GlobalVariables.java b/src/main/java/speiger/src/builder/example/GlobalVariables.java
index 44cb6aa..78ef5e1 100644
--- a/src/main/java/speiger/src/builder/example/GlobalVariables.java
+++ b/src/main/java/speiger/src/builder/example/GlobalVariables.java
@@ -48,14 +48,16 @@ public class GlobalVariables
addSimpleMapper(" NO_GENERIC_TYPE", type.isObject() ? ">" : "");
addSimpleMapper(" KEY_COMPAREABLE_TYPE", type.isObject() ? "<"+type.getKeyType()+" extends Comparable>" : "");
addSimpleMapper(" KEY_SUPER_GENERIC_TYPE", type.isObject() ? " super "+type.getKeyType()+">" : "");
- addSimpleMapper(" VALUE_SUPER_GENERIC_TYPE", valueType.isObject() ? " super "+valueType.getKeyType()+">" : "");
+ addSimpleMapper(" VALUE_SUPER_GENERIC_TYPE", valueType.isObject() ? " super "+valueType.getValueType()+">" : "");
addSimpleMapper(" KEY_VALUE_SUPER_GENERIC_TYPE", type.isObject() ? (valueType.isObject() ? " super "+type.getKeyType()+", ? super "+valueType.getValueType()+">" : " super "+type.getKeyType()+">") : (valueType.isObject() ? " super "+valueType.getValueType()+">" : ""));
-
-
+ addSimpleMapper(" KEY_ENUM_VALUE_GENERIC_TYPE", type.isObject() ? (valueType.isObject() ? "<"+type.getKeyType()+" extends Enum<"+type.getKeyType()+">, "+valueType.getValueType()+">" : "<"+type.getKeyType()+" extends Enum<"+type.getKeyType()+">>") : (valueType.isObject() ? "<"+valueType.getValueType()+">" : ""));
+ addSimpleMapper(" KEY_VALUE_ENUM_GENERIC_TYPE", type.isObject() ? (valueType.isObject() ? "<"+type.getKeyType()+", "+valueType.getValueType()+" extends Enum<"+valueType.getValueType()+">>" : "<"+type.getKeyType()+">") : (valueType.isObject() ? "<"+valueType.getValueType()+" extends Enum<"+valueType.getValueType()+">>" : ""));
+
addSimpleMapper(" GENERIC_KEY_BRACES", type.isObject() ? " <"+type.getKeyType()+">" : "");
addSimpleMapper(" GENERIC_VALUE_BRACES", type.isObject() ? " <"+valueType.getValueType()+">" : "");
addSimpleMapper(" GENERIC_KEY_VALUE_BRACES", type.isObject() ? (valueType.isObject() ? " <"+type.getKeyType()+", "+valueType.getValueType()+">" : " <"+type.getKeyType()+">") : (valueType.isObject() ? " <"+valueType.getValueType()+">" : ""));
addSimpleMapper(" COMPAREABLE_KEY_BRACES", type.isObject() ? " <"+type.getKeyType()+" extends Comparable>" : "");
+ addSimpleMapper("KV_BRACES", type.isObject() || valueType.isObject() ? "<>" : "");
addSimpleMapper("BRACES", type.isObject() ? "<>" : "");
if(type.needsCustomJDKType())
{
@@ -92,7 +94,7 @@ public class GlobalVariables
addInjectMapper(fix+"_TO_OBJ", type.isObject() ? "%s" : type.getClassType(value)+".valueOf(%s)").removeBraces();
addInjectMapper("OBJ_TO_"+fix, type.isObject() ? "%s" : "%s."+type.getKeyType(value)+"Value()").removeBraces();
- addInjectMapper("CLASS_TO_"+fix, "(("+type.getClassType(value)+")%s)."+type.getKeyType(value)+"Value()").removeBraces();
+ addInjectMapper("CLASS_TO_"+fix, type.isObject() ? "("+type.getKeyType(value)+")%s" : "(("+type.getClassType(value)+")%s)."+type.getKeyType(value)+"Value()").removeBraces();
addInjectMapper(fix+"_TO_HASH", type.isObject() ? "%s.hashCode()" : type.getClassType(value)+".hashCode(%s)").removeBraces();
addInjectMapper(fix+"_TO_STRING", type.isObject() ? "%s.toString()" : type.getClassType(value)+".toString(%s)").removeBraces();
@@ -126,6 +128,14 @@ public class GlobalVariables
addClassMapper("LINKED_HASH_SET", "LinkedOpenHashSet");
addClassMapper("CUSTOM_HASH_SET", "OpenCustomHashSet");
addClassMapper("HASH_SET", "OpenHashSet");
+ addBiClassMapper("LINKED_CUSTOM_HASH_MAP", "LinkedOpenCustomHashMap", "2");
+ addBiClassMapper("LINKED_HASH_MAP", "LinkedOpenHashMap", "2");
+ addBiClassMapper("CUSTOM_HASH_MAP", "OpenCustomHashMap", "2");
+ addBiClassMapper("AVL_TREE_MAP", "AVLTreeMap", "2");
+ addBiClassMapper("RB_TREE_MAP", "RBTreeMap", "2");
+ addFunctionValueMappers("ENUM_MAP", valueType.isObject() ? "Enum2ObjectMap" : "Enum2%sMap");
+ addBiClassMapper("HASH_MAP", "OpenHashMap", "2");
+ addBiClassMapper("ARRAY_MAP", "ArrayMap", "2");
addClassMapper("RB_TREE_SET", "RBTreeSet");
addClassMapper("AVL_TREE_SET", "AVLTreeSet");
addClassMapper("ARRAY_SET", "ArraySet");
@@ -155,6 +165,8 @@ public class GlobalVariables
addBiClassMapper("FUNCTION", "Function", "2");
addClassMapper("LIST_ITER", "ListIter");
addClassMapper("LIST", "List");
+ addBiClassMapper("NAVIGABLE_MAP", "NavigableMap", "2");
+ addBiClassMapper("SORTED_MAP", "SortedMap", "2");
addBiClassMapper("MAP", "Map", "2");
addClassMapper("NAVIGABLE_SET", "NavigableSet");
addClassMapper("PRIORITY_QUEUE", "PriorityQueue");
@@ -166,6 +178,10 @@ public class GlobalVariables
addBiClassMapper("UNARY_OPERATOR", "UnaryOperator", "");
if(type.isObject())
{
+ if(!valueType.isObject())
+ {
+ addSimpleMapper("VALUE_CONSUMER", valueType.getFileType()+"Consumer");
+ }
addSimpleMapper("CONSUMER", "Consumer");
addSimpleMapper("COMPARATOR", "Comparator");
addSimpleMapper("IARRAY", "IObjectArray");
@@ -191,13 +207,19 @@ public class GlobalVariables
addFunctionMapper("ENQUEUE", "enqueue");
addFunctionMapper("DEQUEUE_LAST", "dequeueLast");
addFunctionMapper("DEQUEUE", "dequeue");
- addFunctionMappers("ENTRY_KEY", "get%sKey");
- addFunctionValueMappers("ENTRY_VALUE", "get%sValue");
+ addFunctionMappers("POLL_FIRST_ENTRY_KEY", "pollFirst%sKey");
+ addFunctionMappers("POLL_LAST_ENTRY_KEY", "pollLast%sKey");
addFunctionMapper("POLL_FIRST_KEY", "pollFirst");
addFunctionMapper("POLL_LAST_KEY", "pollLast");
+ addFunctionMappers("FIRST_ENTRY_KEY", "first%sKey");
+ addFunctionValueMappers("FIRST_ENTRY_VALUE", "first%sValue");
addFunctionMapper("FIRST_KEY", "first");
+ addFunctionMappers("LAST_ENTRY_KEY", "last%sKey");
+ addFunctionValueMappers("LAST_ENTRY_VALUE", "last%sValue");
+ addFunctionMappers("ENTRY_KEY", "get%sKey");
+ addFunctionValueMappers("ENTRY_VALUE", "get%sValue");
addFunctionMapper("GET_KEY", "get");
- addFunctionValueMapper("GET_VALUE", "get");
+ addFunctionValueMapper("GET_VALUE", valueType.isObject() ? "getObject" : "get");
addFunctionMapper("LAST_KEY", "last");
addFunctionValueMapper("MERGE", "merge");
addFunctionMapper("NEXT", "next");
@@ -229,18 +251,9 @@ public class GlobalVariables
return this;
}
- public TemplateProcess create(String fileName)
+ public TemplateProcess create(String fileName, String splitter, boolean valueOnly)
{
- TemplateProcess process = new TemplateProcess(String.format(fileName+".java", type.getFileType()));
- process.setPathBuilder(new PathBuilder(type.getPathType()));
- process.addFlags(flags);
- process.addMappers(operators);
- return process;
- }
-
- public TemplateProcess createBi(String fileName, String splitter)
- {
- TemplateProcess process = new TemplateProcess(String.format(fileName+".java", type.getFileType()+splitter+valueType.getFileType()));
+ TemplateProcess process = new TemplateProcess(String.format(fileName+".java", (splitter != null ? type.getFileType()+splitter+valueType.getFileType() : (valueOnly ? valueType : type).getFileType())));
process.setPathBuilder(new PathBuilder(type.getPathType()));
process.addFlags(flags);
process.addMappers(operators);
diff --git a/src/main/java/speiger/src/builder/example/TestBuilder.java b/src/main/java/speiger/src/builder/example/TestBuilder.java
index 173364b..401d0af 100644
--- a/src/main/java/speiger/src/builder/example/TestBuilder.java
+++ b/src/main/java/speiger/src/builder/example/TestBuilder.java
@@ -6,8 +6,10 @@ import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.Consumer;
import speiger.src.builder.processor.TemplateProcess;
@@ -15,12 +17,14 @@ import speiger.src.builder.processor.TemplateProcessor;
public class TestBuilder extends TemplateProcessor
{
- Map> blocked = new HashMap>();
- Map nameRemapper = new HashMap();
- Map biRequired = new HashMap();
+ Map> blocked = new HashMap<>();
+ Map nameRemapper = new HashMap<>();
+ Map biRequired = new HashMap<>();
+ Set enumRequired = new HashSet<>();
public static final ClassType[] TYPE = ClassType.values();
- List variables = new ArrayList();
+ List variables = new ArrayList<>();
List biVariables = new ArrayList<>();
+ List enumVariables = new ArrayList<>();
public TestBuilder()
{
@@ -61,21 +65,20 @@ public class TestBuilder extends TemplateProcessor
create(clzType, subType);
}
}
-// blocked.put("AbstractMap", EnumSet.allOf(ClassType.class));
+ enumRequired.add("EnumMap");
biRequired.put("BiConsumer", "");
- biRequired.put("Function", "2");
biRequired.put("UnaryOperator", "");
- biRequired.put("Map", "2");
- biRequired.put("Maps", "2");
- biRequired.put("AbstractMap", "2");
+ addBiClass("Function", "Maps", "Map", "SortedMap", "NavigableMap", "AbstractMap", "OpenHashMap", "LinkedOpenHashMap", "OpenCustomHashMap", "LinkedOpenCustomHashMap", "ArrayMap", "RBTreeMap", "AVLTreeMap");
nameRemapper.put("BiConsumer", "%sConsumer");
nameRemapper.put("IArray", "I%sArray");
nameRemapper.put("AbstractMap", "Abstract%sMap");
nameRemapper.put("AbstractCollection", "Abstract%sCollection");
nameRemapper.put("AbstractSet", "Abstract%sSet");
nameRemapper.put("AbstractList", "Abstract%sList");
+ nameRemapper.put("EnumMap", "Enum2%sMap");
addBlockage(ClassType.OBJECT, "Consumer", "Comparator", "Stack");
addBlockage(ClassType.BOOLEAN, "Sets", "ArraySet", "AVLTreeSet", "RBTreeSet", "SortedSet", "NavigableSet", "OpenHashSet", "OpenCustomHashSet", "LinkedOpenHashSet", "LinkedOpenCustomHashSet");
+ addBlockage(ClassType.BOOLEAN, "SortedMap", "NavigableMap", "OpenHashMap", "LinkedOpenHashMap", "OpenCustomHashMap", "LinkedOpenCustomHashMap", "ArrayMap", "RBTreeMap", "AVLTreeMap");
}
protected void create(ClassType mainType, ClassType subType)
@@ -89,12 +92,24 @@ public class TestBuilder extends TemplateProcessor
type.createFunctions();
if(mainType == subType) variables.add(type);
biVariables.add(type);
+ if(mainType.isObject()) enumVariables.add(type);
}
- protected void addBlockage(ClassType type, String...args) {
- for(String s : args) {
+ protected void addBiClass(String...classNames)
+ {
+ for(String s : classNames)
+ {
+ biRequired.put(s, "2");
+ }
+ }
+
+ protected void addBlockage(ClassType type, String...args)
+ {
+ for(String s : args)
+ {
EnumSet set = blocked.get(s);
- if(set == null) {
+ if(set == null)
+ {
set = EnumSet.noneOf(ClassType.class);
blocked.put(s, set);
}
@@ -105,30 +120,26 @@ public class TestBuilder extends TemplateProcessor
@Override
public void createProcesses(String name, Consumer acceptor)
{
- EnumSet types = blocked.get(name);
String splitter = biRequired.get(name);
- if(splitter != null)
+ boolean valueRequired = enumRequired.contains(name);
+ List vars = getVariablesByClass(name, splitter != null);
+ EnumSet types = blocked.get(name);
+ for(int i = 0,m=vars.size();i getVariablesByClass(String name, boolean bi) {
+ if(enumRequired.contains(name)) return enumVariables;
+ if(bi) return biVariables;
+ return variables;
+ }
+
public static void main(String...args)
{
try
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/abstracts/AbstractMap.template b/src/main/resources/speiger/assets/collections/templates/maps/abstracts/AbstractMap.template
index 8e4dff3..0ccc4f7 100644
--- a/src/main/resources/speiger/assets/collections/templates/maps/abstracts/AbstractMap.template
+++ b/src/main/resources/speiger/assets/collections/templates/maps/abstracts/AbstractMap.template
@@ -27,7 +27,7 @@ import speiger.src.collections.objects.sets.ObjectSet;
public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap implements MAP KEY_VALUE_GENERIC_TYPE
{
- VALUE_TYPE defaultReturnValue = EMPTY_VALUE;
+ protected VALUE_TYPE defaultReturnValue = EMPTY_VALUE;
@Override
public VALUE_TYPE getDefaultReturnValue() {
@@ -174,6 +174,11 @@ public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap entry = (Map.Entry, ?>)obj;
Object key = entry.getKey();
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/impl/customHash/LinkedOpenCustomHashMap.template b/src/main/resources/speiger/assets/collections/templates/maps/impl/customHash/LinkedOpenCustomHashMap.template
new file mode 100644
index 0000000..8aa9ebc
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/impl/customHash/LinkedOpenCustomHashMap.template
@@ -0,0 +1,999 @@
+package speiger.src.collections.PACKAGE.maps.impl.customHash;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.function.Consumer;
+
+import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.functions.COMPARATOR;
+import speiger.src.collections.PACKAGE.functions.CONSUMER;
+#endif
+import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
+import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
+import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.SORTED_MAP;
+import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
+import speiger.src.collections.PACKAGE.sets.SORTED_SET;
+import speiger.src.collections.PACKAGE.sets.SET;
+import speiger.src.collections.PACKAGE.utils.STRATEGY;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
+#if !VALUE_OBJECT && !SAME_TYPE
+import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER;
+import speiger.src.collections.VALUE_PACKAGE.lists.VALUE_LIST_ITERATOR;
+#endif
+#if !TYPE_OBJECT
+import speiger.src.collections.objects.collections.ObjectBidirectionalIterator;
+import speiger.src.collections.objects.lists.ObjectListIterator;
+import speiger.src.collections.objects.sets.AbstractObjectSet;
+import speiger.src.collections.objects.sets.ObjectSortedSet;
+import speiger.src.collections.objects.sets.ObjectSet;
+#endif
+import speiger.src.collections.utils.HashUtil;
+
+public class LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE implements SORTED_MAP KEY_VALUE_GENERIC_TYPE
+{
+ protected transient long[] links;
+ protected int firstIndex = -1;
+ protected int lastIndex = -1;
+
+ public LINKED_CUSTOM_HASH_MAP(STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public LINKED_CUSTOM_HASH_MAP(int minCapacity, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public LINKED_CUSTOM_HASH_MAP(int minCapacity, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ super(minCapacity, loadFactor, strategy);
+ links = new long[nullIndex + 1];
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ public LINKED_CUSTOM_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public LINKED_CUSTOM_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(keys.length, loadFactor, strategy);
+ if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
+ for(int i = 0,m=keys.length;i map, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(map, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public LINKED_CUSTOM_HASH_MAP(Map extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(map.size(), loadFactor, strategy);
+ putAll(map);
+ }
+
+ public LINKED_CUSTOM_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(map, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public LINKED_CUSTOM_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(map.size(), loadFactor, strategy);
+ putAll(map);
+ }
+
+ @Override
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) {
+ if(strategy.equals(key, EMPTY_KEY_VALUE)) {
+ if(containsNull) {
+ VALUE_TYPE lastValue = values[nullIndex];
+ values[nullIndex] = value;
+ moveToFirstIndex(nullIndex);
+ return lastValue;
+ }
+ values[nullIndex] = value;
+ containsNull = true;
+ onNodeAdded(nullIndex);
+ }
+ else {
+ int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
+ while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
+ if(strategy.equals(keys[pos], key)) {
+ VALUE_TYPE lastValue = values[pos];
+ values[pos] = value;
+ moveToFirstIndex(pos);
+ return lastValue;
+ }
+ pos = ++pos & mask;
+ }
+ keys[pos] = key;
+ values[pos] = value;
+ onNodeAdded(pos);
+ }
+ if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) {
+ if(strategy.equals(key, EMPTY_KEY_VALUE)) {
+ if(containsNull) {
+ VALUE_TYPE lastValue = values[nullIndex];
+ values[nullIndex] = value;
+ moveToLastIndex(nullIndex);
+ return lastValue;
+ }
+ values[nullIndex] = value;
+ containsNull = true;
+ onNodeAdded(nullIndex);
+ }
+ else {
+ int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
+ while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
+ if(strategy.equals(keys[pos], key)) {
+ VALUE_TYPE lastValue = values[pos];
+ values[pos] = value;
+ moveToLastIndex(pos);
+ return lastValue;
+ }
+ pos = ++pos & mask;
+ }
+ keys[pos] = key;
+ values[pos] = value;
+ onNodeAdded(pos);
+ }
+ if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public boolean moveToFirst(KEY_TYPE key) {
+ if(strategy.equals(FIRST_ENTRY_KEY(), key)) return false;
+ if(strategy.equals(key, EMPTY_KEY_VALUE)) {
+ if(containsNull) {
+ moveToFirstIndex(nullIndex);
+ return true;
+ }
+ }
+ else {
+ int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
+ while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
+ if(strategy.equals(keys[pos], key)) {
+ moveToFirstIndex(pos);
+ return true;
+ }
+ pos = ++pos & mask;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean moveToLast(KEY_TYPE key) {
+ if(strategy.equals(LAST_ENTRY_KEY(), key)) return false;
+ if(strategy.equals(key, EMPTY_KEY_VALUE)) {
+ if(containsNull) {
+ moveToLastIndex(nullIndex);
+ return true;
+ }
+ }
+ else {
+ int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
+ while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
+ if(strategy.equals(keys[pos], key)) {
+ moveToLastIndex(pos);
+ return true;
+ }
+ pos = ++pos & mask;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index < 0) return getDefaultReturnValue();
+ moveToFirstIndex(index);
+ return values[index];
+ }
+
+ @Override
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index < 0) return getDefaultReturnValue();
+ moveToLastIndex(index);
+ return values[index];
+ }
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() {
+ return null;
+ }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public KEY_TYPE FIRST_ENTRY_KEY() {
+ if(size == 0) throw new NoSuchElementException();
+ return keys[firstIndex];
+ }
+
+ @Override
+ 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;
+ KEY_TYPE result = keys[pos];
+ size--;
+ if(strategy.equals(result, EMPTY_KEY_VALUE)) {
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ }
+ else shiftKeys(pos);
+ if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
+ return result;
+ }
+
+ @Override
+ public KEY_TYPE LAST_ENTRY_KEY() {
+ if(size == 0) throw new NoSuchElementException();
+ return keys[lastIndex];
+ }
+
+ @Override
+ 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;
+ KEY_TYPE result = keys[pos];
+ size--;
+ if(strategy.equals(result, EMPTY_KEY_VALUE)) {
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ }
+ else shiftKeys(pos);
+ if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
+ return result;
+ }
+
+ @Override
+ public VALUE_TYPE FIRST_ENTRY_VALUE() {
+ if(size == 0) throw new NoSuchElementException();
+ return values[firstIndex];
+ }
+
+ @Override
+ public VALUE_TYPE LAST_ENTRY_VALUE() {
+ if(size == 0) throw new NoSuchElementException();
+ return values[lastIndex];
+ }
+
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new MapEntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet() {
+ if(keySet == null) keySet = new KeySet();
+ return keySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(values == null) valuesC = new Values();
+ return valuesC;
+ }
+
+ @Override
+ public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(keys[index], values[index]);
+ index = (int)links[index];
+ }
+ }
+
+ @Override
+ public void clear() {
+ super.clear();
+ firstIndex = lastIndex = -1;
+ }
+
+ protected void moveToFirstIndex(int startPos) {
+ if(size == 1 || firstIndex == startPos) return;
+ if(lastIndex == startPos) {
+ lastIndex = (int)(links[startPos] >>> 32);
+ links[lastIndex] |= 0xFFFFFFFFL;
+ }
+ else {
+ long link = links[startPos];
+ int prev = (int)(link >>> 32);
+ int next = (int)link;
+ links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
+ }
+ links[firstIndex] ^= ((links[firstIndex] ^ ((startPos & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ links[startPos] = 0xFFFFFFFF00000000L | (firstIndex & 0xFFFFFFFFL);
+ firstIndex = startPos;
+ }
+
+ protected void moveToLastIndex(int startPos) {
+ if(size == 1 || lastIndex == startPos) return;
+ if(firstIndex == startPos) {
+ firstIndex = (int)links[startPos];
+ links[lastIndex] |= 0xFFFFFFFF00000000L;
+ }
+ else {
+ long link = links[startPos];
+ int prev = (int)(link >>> 32);
+ int next = (int)link;
+ links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
+ }
+ links[lastIndex] ^= ((links[lastIndex] ^ (startPos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[startPos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
+ lastIndex = startPos;
+ }
+
+ @Override
+ protected void onNodeAdded(int pos) {
+ if(size == 0) {
+ firstIndex = lastIndex = pos;
+ links[pos] = -1L;
+ }
+ else {
+ links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
+ lastIndex = pos;
+ }
+ }
+
+ @Override
+ protected void onNodeRemoved(int pos) {
+ if(size == 0) firstIndex = lastIndex = -1;
+ else if(firstIndex == pos) {
+ firstIndex = (int)links[pos];
+ if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
+ }
+ else if(lastIndex == pos) {
+ lastIndex = (int)(links[pos] >>> 32);
+ if(0 <= lastIndex) links[pos] |= 0xFFFFFFFFL;
+ }
+ else {
+ long link = links[pos];
+ int prev = (int)(link >>> 32);
+ int next = (int)link;
+ links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
+ }
+ }
+
+ @Override
+ protected void onNodeMoved(int from, int to) {
+ if(size == 1) {
+ firstIndex = lastIndex = to;
+ links[to] = -1L;
+ }
+ else if(firstIndex == from) {
+ firstIndex = to;
+ links[(int)links[from]] ^= ((links[(int)links[from]] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ links[to] = links[from];
+ }
+ else if(lastIndex == from) {
+ lastIndex = to;
+ links[(int)(links[from] >>> 32)] ^= ((links[(int)(links[from] >>> 32)] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[to] = links[from];
+ }
+ else {
+ long link = links[from];
+ int prev = (int)(link >>> 32);
+ int next = (int)link;
+ links[prev] ^= ((links[prev] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[next] ^= ((links[next] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ links[to] = link;
+ }
+ }
+
+ @Override
+ protected void rehash(int newSize) {
+ int newMask = newSize - 1;
+ KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
+ VALUE_TYPE[] newValues = NEW_VALUE_ARRAY(newSize + 1);
+ long[] newLinks = new long[newSize + 1];
+ int newPrev = -1;
+ for(int j = size, i = firstIndex, pos = 0, prev = -1;j != 0;) {
+ if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) pos = newSize;
+ else {
+ pos = HashUtil.mix(strategy.hashCode(keys[i])) & newMask;
+ while(!strategy.equals(newKeys[pos], EMPTY_KEY_VALUE)) pos = ++pos & newMask;
+ }
+ newKeys[pos] = keys[i];
+ newValues[pos] = values[i];
+ if(prev != -1) {
+ newLinks[newPrev] ^= ((newLinks[newPrev] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ newLinks[pos] ^= ((newLinks[pos] ^ ((newPrev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ newPrev = pos;
+ }
+ else {
+ newPrev = firstIndex = pos;
+ newLinks[pos] = -1L;
+ }
+ i = (int)links[prev = i];
+ }
+ links = newLinks;
+ lastIndex = newPrev;
+ if(newPrev != -1) newLinks[newPrev] |= 0xFFFFFFFFL;
+ nullIndex = newSize;
+ mask = newMask;
+ maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
+ keys = newKeys;
+ }
+
+ private class MapEntrySet extends AbstractObjectSet implements SORTED_MAP.FastSortedSet KEY_VALUE_GENERIC_TYPE {
+ @Override
+ public boolean addAndMoveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public boolean moveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
+ return LINKED_CUSTOM_HASH_MAP.this.moveToFirst(o.ENTRY_KEY());
+ }
+
+ @Override
+ public boolean moveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
+ return LINKED_CUSTOM_HASH_MAP.this.moveToLast(o.ENTRY_KEY());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE first() {
+ return new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE last() {
+ return new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirst() {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
+ POLL_FIRST_ENTRY_KEY();
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLast() {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
+ POLL_LAST_ENTRY_KEY();
+ return entry;
+ }
+
+ @Override
+ public ObjectBidirectionalIterator iterator() {
+ return new EntryIterator();
+ }
+
+ @Override
+ public ObjectBidirectionalIterator iterator(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) {
+ return new EntryIterator(fromElement.ENTRY_KEY());
+ }
+
+ @Override
+ public ObjectBidirectionalIterator fastIterator() {
+ return new FastEntryIterator();
+ }
+
+ @Override
+ public ObjectBidirectionalIterator fastIterator(KEY_TYPE fromElement) {
+ return new FastEntryIterator(fromElement);
+ }
+
+ @Override
+ public void forEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(new BasicEntryKV_BRACES(keys[index], values[index]));
+ index = (int)links[index];
+ }
+ }
+
+ @Override
+ public void fastForEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
+ int index = firstIndex;
+ while(index != -1){
+ entry.set(keys[index], values[index]);
+ action.accept(entry);
+ index = (int)links[index];
+ }
+ }
+
+ @Override
+ @Deprecated
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) return LINKED_CUSTOM_HASH_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
+ return LINKED_CUSTOM_HASH_MAP.this.containsKey(((Map.Entry, ?>)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return LINKED_CUSTOM_HASH_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return LINKED_CUSTOM_HASH_MAP.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return LINKED_CUSTOM_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ LINKED_CUSTOM_HASH_MAP.this.clear();
+ }
+
+ @Override
+ public Comparator comparator() {
+ return null;
+ }
+ @Override
+ public ObjectSortedSet subSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement, MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
+ @Override
+ public ObjectSortedSet headSet(MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
+ @Override
+ public ObjectSortedSet tailSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) { throw new UnsupportedOperationException(); }
+ }
+
+ private final class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
+#if TYPE_OBJECT
+ @Override
+ @Deprecated
+ public boolean contains(Object e) {
+ return containsKey(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#else
+ @Override
+ public boolean contains(KEY_TYPE e) {
+ return containsKey(e);
+ }
+
+ @Override
+ public boolean remove(KEY_TYPE o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#endif
+ @Override
+ public boolean add(KEY_TYPE o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public boolean moveToFirst(KEY_TYPE o) {
+ return LINKED_CUSTOM_HASH_MAP.this.moveToFirst(o);
+ }
+
+ @Override
+ public boolean moveToLast(KEY_TYPE o) {
+ return LINKED_CUSTOM_HASH_MAP.this.moveToLast(o);
+ }
+
+ @Override
+ public LIST_ITERATOR KEY_GENERIC_TYPE iterator() {
+ return new KeyIterator();
+ }
+
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
+ return new KeyIterator(fromElement);
+ }
+
+ @Override
+ public int size() {
+ return LINKED_CUSTOM_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ LINKED_CUSTOM_HASH_MAP.this.clear();
+ }
+
+ @Override
+ public KEY_TYPE FIRST_KEY() {
+ return FIRST_ENTRY_KEY();
+ }
+
+ @Override
+ public KEY_TYPE POLL_FIRST_KEY() {
+ return POLL_FIRST_ENTRY_KEY();
+ }
+
+ @Override
+ public KEY_TYPE LAST_KEY() {
+ return LAST_ENTRY_KEY();
+ }
+
+ @Override
+ public KEY_TYPE POLL_LAST_KEY() {
+ return POLL_LAST_ENTRY_KEY();
+ }
+
+#if TYPE_OBJECT
+ @Override
+ public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(keys[index]);
+ index = (int)links[index];
+ }
+ }
+
+#else
+ @Override
+ public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(keys[index]);
+ index = (int)links[index];
+ }
+ }
+
+#endif
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return null; }
+
+ @Override
+ public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { throw new UnsupportedOperationException(); }
+ }
+
+ private class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+#if VALUE_OBJECT
+ @Override
+ @Deprecated
+ public boolean contains(Object e) {
+ return containsValue(e);
+ }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) {
+ return containsValue(e);
+ }
+
+#endif
+ @Override
+ public boolean add(VALUE_TYPE o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
+ return new ValueIterator();
+ }
+
+ @Override
+ public int size() {
+ return LINKED_CUSTOM_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ LINKED_CUSTOM_HASH_MAP.this.clear();
+ }
+
+#if VALUE_OBJECT
+ @Override
+ public void forEach(Consumer VALUE_SUPER_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(values[index]);
+ index = (int)links[index];
+ }
+ }
+#else
+ @Override
+ public void forEach(VALUE_CONSUMER VALUE_SUPER_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(values[index]);
+ index = (int)links[index];
+ }
+ }
+#endif
+ }
+
+ private class FastEntryIterator extends MapIterator implements ObjectListIterator {
+ MapEntry entry = new MapEntry(nextEntry());
+
+ public FastEntryIterator() {}
+ public FastEntryIterator(KEY_TYPE from) {
+ super(from);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ entry.index = nextEntry();
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ entry.index = previousEntry();
+ return entry;
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
+ }
+
+ private class EntryIterator extends MapIterator implements ObjectListIterator {
+ MapEntry entry;
+
+ public EntryIterator() {}
+ public EntryIterator(KEY_TYPE from) {
+ super(from);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ return entry = new MapEntry(nextEntry());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ return entry = new MapEntry(previousEntry());
+ }
+
+ @Override
+ public void remove() {
+ super.remove();
+ entry.index = -1;
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
+ }
+
+ private class KeyIterator extends MapIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
+
+ public KeyIterator() {}
+ public KeyIterator(KEY_TYPE from) {
+ super(from);
+ }
+
+ @Override
+ public KEY_TYPE PREVIOUS() {
+ return keys[previousEntry()];
+ }
+
+ @Override
+ public KEY_TYPE NEXT() {
+ return keys[nextEntry()];
+ }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class ValueIterator extends MapIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
+ public ValueIterator() {}
+
+ @Override
+ public VALUE_TYPE VALUE_PREVIOUS() {
+ return values[previousEntry()];
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return values[nextEntry()];
+ }
+
+ @Override
+ public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+
+ }
+
+ private class MapIterator {
+ int previous = -1;
+ int next = -1;
+ int current = -1;
+ int index = 0;
+
+ MapIterator() {
+ next = firstIndex;
+ }
+
+ MapIterator(KEY_TYPE from) {
+ if(strategy.equals(from, EMPTY_KEY_VALUE)) {
+ if(containsNull) {
+ next = (int) links[nullIndex];
+ previous = nullIndex;
+ }
+ else throw new NoSuchElementException("The null element is not in the set");
+ }
+ else if(keys[lastIndex] == from) {
+ previous = lastIndex;
+ index = size;
+ }
+ else {
+ int pos = HashUtil.mix(strategy.hashCode(from)) & mask;
+ while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
+ if(strategy.equals(keys[pos], from)) {
+ next = (int)links[pos];
+ previous = pos;
+ break;
+ }
+ pos = ++pos & mask;
+ }
+ if(previous == -1 && next == -1)
+ throw new NoSuchElementException("The element was not found");
+ }
+ }
+
+ public boolean hasNext() {
+ return next != -1;
+ }
+
+ public boolean hasPrevious() {
+ return previous != -1;
+ }
+
+ public int nextIndex() {
+ ensureIndexKnown();
+ return index;
+ }
+
+ public int previousIndex() {
+ ensureIndexKnown();
+ return index - 1;
+ }
+
+ public void remove() {
+ if(current == -1) throw new IllegalStateException();
+ ensureIndexKnown();
+ if(current == previous) {
+ index--;
+ previous = (int)(links[current] >>> 32);
+ }
+ else next = (int)links[current];
+ size--;
+ if(previous == -1) firstIndex = next;
+ else links[previous] ^= ((links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+
+ if (next == -1) lastIndex = previous;
+ else links[next] ^= ((links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ if(current == nullIndex) {
+ current = -1;
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ }
+ else {
+ int slot, last, startPos = current;
+ current = -1;
+ KEY_TYPE current;
+ while(true) {
+ startPos = ((last = startPos) + 1) & mask;
+ while(true){
+ if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
+ keys[last] = EMPTY_KEY_VALUE;
+ values[last] = EMPTY_VALUE;
+ return;
+ }
+ slot = HashUtil.mix(strategy.hashCode(current)) & mask;
+ if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
+ startPos = ++startPos & mask;
+ }
+ keys[last] = current;
+ values[last] = values[startPos];
+ if(next == startPos) next = last;
+ if(previous == startPos) previous = last;
+ onNodeMoved(startPos, last);
+ }
+ }
+ }
+
+ public int previousEntry() {
+ if(!hasPrevious()) throw new NoSuchElementException();
+ current = previous;
+ previous = (int)(links[current] >> 32);
+ next = current;
+ if(index >= 0) index--;
+ return current;
+ }
+
+ public int nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ current = next;
+ next = (int)(links[current]);
+ previous = current;
+ if(index >= 0) index++;
+ return current;
+ }
+
+ private void ensureIndexKnown() {
+ if(index == -1) {
+ if(previous == -1) {
+ index = 0;
+ }
+ else if(next == -1) {
+ index = size;
+ }
+ else {
+ index = 1;
+ for(int pos = firstIndex;pos != previous;pos = (int)links[pos], index++);
+ }
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template b/src/main/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template
new file mode 100644
index 0000000..bbb6cd1
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template
@@ -0,0 +1,781 @@
+package speiger.src.collections.PACKAGE.maps.impl.customHash;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.collections.ITERATOR;
+import speiger.src.collections.PACKAGE.functions.CONSUMER;
+#endif
+import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
+import speiger.src.collections.PACKAGE.lists.ARRAY_LIST;
+import speiger.src.collections.PACKAGE.lists.LIST;
+import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
+import speiger.src.collections.PACKAGE.sets.SET;
+#endif
+import speiger.src.collections.PACKAGE.utils.STRATEGY;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+#if !SAME_TYPE && !VALUE_OBJECT
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
+import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER;
+#endif
+import speiger.src.collections.objects.collections.ObjectIterator;
+import speiger.src.collections.objects.sets.AbstractObjectSet;
+import speiger.src.collections.objects.sets.ObjectSet;
+import speiger.src.collections.utils.HashUtil;
+
+public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE
+{
+ protected transient KEY_TYPE[] keys;
+ protected transient VALUE_TYPE[] values;
+ protected transient boolean containsNull;
+ protected transient int minCapacity;
+ protected transient int nullIndex;
+ protected transient int maxFill;
+ protected transient int mask;
+ protected transient FastEntrySet KEY_VALUE_GENERIC_TYPE entrySet;
+ protected transient SET KEY_GENERIC_TYPE keySet;
+ protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC;
+
+ protected int size;
+ protected final float loadFactor;
+ protected final STRATEGY KEY_SUPER_GENERIC_TYPE strategy;
+
+ public CUSTOM_HASH_MAP(STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public CUSTOM_HASH_MAP(int minCapacity, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public CUSTOM_HASH_MAP(int minCapacity, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ if(minCapacity < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed");
+ if(loadFactor <= 0 || loadFactor >= 1F) throw new IllegalStateException("Load Factor is not between 0 and 1");
+ this.loadFactor = loadFactor;
+ this.minCapacity = nullIndex = HashUtil.arraySize(minCapacity, loadFactor);
+ this.strategy = strategy;
+ mask = nullIndex - 1;
+ maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
+ keys = NEW_KEY_ARRAY(nullIndex + 1);
+ values = NEW_VALUE_ARRAY(nullIndex + 1);
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ public CUSTOM_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public CUSTOM_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(keys.length, loadFactor, strategy);
+ if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
+ for(int i = 0,m=keys.length;i map, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(map, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public CUSTOM_HASH_MAP(Map extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(map.size(), loadFactor, strategy);
+ putAll(map);
+ }
+
+ public CUSTOM_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(map, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
+ }
+
+ public CUSTOM_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
+ this(map.size(), loadFactor, strategy);
+ putAll(map);
+ }
+
+ @Override
+ public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
+ int slot = findIndex(key);
+ if(slot < 0) {
+ insert(-slot-1, key, value);
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE oldValue = values[slot];
+ values[slot] = value;
+ return oldValue;
+ }
+
+ @Override
+ public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
+ int slot = findIndex(key);
+ if(slot < 0) {
+ insert(-slot-1, key, value);
+ return getDefaultReturnValue();
+ }
+ return values[slot];
+ }
+
+#if VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
+ int slot = findIndex(key);
+ if(slot < 0) {
+ insert(-slot-1, key, value);
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE oldValue = values[slot];
+ values[slot] += value;
+ return oldValue;
+ }
+
+#endif
+#if !TYPE_OBJECT
+ @Override
+ public boolean containsKey(KEY_TYPE key) {
+ return findIndex(key) >= 0;
+ }
+
+#endif
+ @Override
+ @Deprecated
+ public boolean containsKey(Object key) {
+ return findIndex(key) >= 0;
+ }
+
+#if !VALUE_OBJECT
+ @Override
+ public boolean containsValue(VALUE_TYPE value) {
+ if(VALUE_EQUALS(value, values[nullIndex])) return true;
+ for(int i = nullIndex-1;i >= 0;i--)
+ if(!strategy.equals(keys[i], EMPTY_KEY_VALUE) && VALUE_EQUALS(values[i], value)) return true;
+ return false;
+ }
+
+#endif
+ @Override
+ @Deprecated
+ public boolean containsValue(Object value) {
+ if((value == null && VALUE_EQUALS(values[nullIndex], getDefaultReturnValue())) || EQUALS_VALUE_TYPE(values[nullIndex], value)) return true;
+ for(int i = nullIndex-1;i >= 0;i--)
+ if(!strategy.equals(keys[i], EMPTY_KEY_VALUE) && ((value == null && values[i] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[i], value))) return true;
+ return false;
+ }
+
+ @Override
+ public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
+ int slot = findIndex(key);
+ if(slot < 0) return getDefaultReturnValue();
+ return removeIndex(slot);
+ }
+
+ @Override
+ @Deprecated
+ public CLASS_VALUE_TYPE remove(Object key) {
+ int slot = findIndex(key);
+ if(slot < 0) return VALUE_TO_OBJ(getDefaultReturnValue());
+ return removeIndex(slot);
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ @Override
+ public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
+ if(strategy.equals(key, EMPTY_KEY_VALUE)) {
+ if(containsNull && VALUE_EQUALS(value, values[nullIndex])) {
+ removeNullIndex();
+ return true;
+ }
+ return false;
+ }
+ int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
+ KEY_TYPE current = keys[pos];
+ if(strategy.equals(current, EMPTY_KEY_VALUE)) return false;
+ if(strategy.equals(current, key) && VALUE_EQUALS(value, values[pos])) {
+ removeIndex(pos);
+ return true;
+ }
+ while(true) {
+ if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE)) return false;
+ else if(strategy.equals(current, key) && VALUE_EQUALS(value, values[pos])) {
+ removeIndex(pos);
+ return true;
+ }
+ }
+ }
+
+#endif
+ @Override
+ public boolean remove(Object key, Object value) {
+ Objects.requireNonNull(value);
+ if(key == null) {
+ if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
+ removeNullIndex();
+ return true;
+ }
+ return false;
+ }
+ KEY_TYPE keyType = CLASS_TO_KEY(key);
+ int pos = HashUtil.mix(strategy.hashCode(keyType)) & mask;
+ KEY_TYPE current = keys[pos];
+ if(strategy.equals(current, EMPTY_KEY_VALUE)) return false;
+ if(strategy.equals(current, keyType) && EQUALS_VALUE_TYPE(values[pos], value)) {
+ removeIndex(pos);
+ return true;
+ }
+ while(true) {
+ if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE)) return false;
+ else if(strategy.equals(current, keyType) && EQUALS_VALUE_TYPE(values[pos], value)){
+ removeIndex(pos);
+ return true;
+ }
+ }
+ }
+
+ @Override
+ public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
+ int slot = findIndex(key);
+ return slot < 0 ? getDefaultReturnValue() : values[slot];
+ }
+
+ @Override
+ public CLASS_VALUE_TYPE get(Object key) {
+ int slot = findIndex(key);
+ return VALUE_TO_OBJ(slot < 0 ? getDefaultReturnValue() : values[slot]);
+ }
+
+#if !TYPE_OBJECT
+ @Override
+ public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
+ int slot = findIndex(key);
+ return slot < 0 ? defaultValue : values[slot];
+ }
+
+#endif
+ @Override
+ public CLASS_VALUE_TYPE getOrDefault(Object key, CLASS_VALUE_TYPE defaultValue) {
+ int slot = findIndex(key);
+ return slot < 0 ? defaultValue : VALUE_TO_OBJ(values[slot]);
+ }
+
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new MapEntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet() {
+ if(keySet == null) keySet = new KeySet();
+ return keySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(valuesC == null) valuesC = new Values();
+ return valuesC;
+ }
+
+ @Override
+ public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
+ if(size() <= 0) return;
+ if(containsNull) action.accept(keys[nullIndex], values[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--) {
+ if(!strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(keys[i], values[i]);
+ }
+ }
+
+ @Override
+ public void clear() {
+ if(size == 0) return;
+ size = 0;
+ containsNull = false;
+ Arrays.fill(keys, EMPTY_KEY_VALUE);
+ Arrays.fill(values, EMPTY_VALUE);
+ }
+
+#if !TYPE_OBJECT
+ protected int findIndex(KEY_TYPE key) {
+ if(KEY_EQUALS_NULL(key)) return containsNull ? nullIndex : -(nullIndex + 1);
+ int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
+ KEY_TYPE current = keys[pos];
+ if(!strategy.equals(current, EMPTY_KEY_VALUE)) {
+ if(strategy.equals(current, key)) return pos;
+ while(!strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE))
+ if(strategy.equals(current, key)) return pos;
+ }
+ return -(pos + 1);
+ }
+
+#endif
+ protected int findIndex(Object key) {
+ if(key == null) return containsNull ? nullIndex : -(nullIndex + 1);
+ KEY_TYPE keyType = CLASS_TO_KEY(key);
+ int pos = HashUtil.mix(strategy.hashCode(keyType)) & mask;
+ KEY_TYPE current = keys[pos];
+ if(!strategy.equals(current, EMPTY_KEY_VALUE)) {
+ if(strategy.equals(current, keyType)) return pos;
+ while(!strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE))
+ if(strategy.equals(current, keyType)) return pos;
+ }
+ return -(pos + 1);
+ }
+
+ protected VALUE_TYPE removeIndex(int pos) {
+ VALUE_TYPE value = values[pos];
+ size--;
+ onNodeRemoved(pos);
+ shiftKeys(pos);
+ if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
+ return value;
+ }
+
+ protected VALUE_TYPE removeNullIndex() {
+ VALUE_TYPE value = values[nullIndex];
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ size--;
+ onNodeRemoved(nullIndex);
+ if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
+ return value;
+ }
+
+ protected void insert(int slot, KEY_TYPE key, VALUE_TYPE value) {
+ if(slot == nullIndex) containsNull = true;
+ keys[slot] = key;
+ values[slot] = value;
+ onNodeAdded(slot);
+ if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
+ }
+
+ protected void rehash(int newSize) {
+ int newMask = newSize - 1;
+ KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
+ VALUE_TYPE[] newValues = NEW_VALUE_ARRAY(newSize + 1);
+ for(int i = nullIndex, pos = 0, j = (size - (containsNull ? 1 : 0));j-- != 0;) {
+ while(strategy.equals(keys[--i], EMPTY_KEY_VALUE));
+ if(!strategy.equals(newKeys[pos = HashUtil.mix(strategy.hashCode(keys[i])) & newMask], EMPTY_KEY_VALUE))
+ while(!strategy.equals(newKeys[pos = (++pos & newMask)], EMPTY_KEY_VALUE));
+ newKeys[pos] = keys[i];
+ newValues[pos] = values[i];
+ }
+ newValues[newSize] = values[nullIndex];
+ nullIndex = newSize;
+ mask = newMask;
+ maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
+ keys = newKeys;
+ values = newValues;
+ }
+
+ protected void onNodeAdded(int pos) {
+
+ }
+
+ protected void onNodeRemoved(int pos) {
+
+ }
+
+ protected void onNodeMoved(int from, int to) {
+
+ }
+
+ protected void shiftKeys(int startPos) {
+ int slot, last;
+ KEY_TYPE current;
+ while(true) {
+ startPos = ((last = startPos) + 1) & mask;
+ while(true){
+ if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
+ keys[last] = EMPTY_KEY_VALUE;
+ values[last] = EMPTY_VALUE;
+ return;
+ }
+ slot = HashUtil.mix(strategy.hashCode(current)) & mask;
+ if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
+ startPos = ++startPos & mask;
+ }
+ keys[last] = current;
+ values[last] = values[startPos];
+ onNodeMoved(startPos, last);
+ }
+ }
+
+ protected class MapEntry implements MAP.Entry KEY_VALUE_GENERIC_TYPE, Map.Entry {
+ public int index = -1;
+
+ public MapEntry() {}
+ public MapEntry(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public KEY_TYPE ENTRY_KEY() {
+ return keys[index];
+ }
+
+ @Override
+ public VALUE_TYPE ENTRY_VALUE() {
+ return values[index];
+ }
+
+ @Override
+ public VALUE_TYPE setValue(VALUE_TYPE value) {
+ VALUE_TYPE oldValue = values[index];
+ values[index] = value;
+ return oldValue;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(obj instanceof Map.Entry) {
+ if(obj instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)obj;
+ return KEY_EQUALS(keys[index], entry.ENTRY_KEY()) && VALUE_EQUALS(values[index], entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)obj;
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+#if TYPE_OBJECT && VALUE_OBJECT
+ return KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], value);
+#else if TYPE_OBJECT
+ return value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
+#else if VALUE_OBJECT
+ return key instanceof CLASS_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], value);
+#else
+ return key instanceof CLASS_TYPE && value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
+#endif
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return strategy.hashCode(keys[index]) ^ VALUE_TO_HASH(values[index]);
+ }
+
+ @Override
+ public String toString() {
+ return KEY_TO_STRING(keys[index]) + "->" + VALUE_TO_STRING(values[index]);
+ }
+ }
+
+ private final class MapEntrySet extends AbstractObjectSet implements MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE {
+ @Override
+ public ObjectIterator fastIterator() {
+ return new FastEntryIterator();
+ }
+
+ @Override
+ public ObjectIterator iterator() {
+ return new EntryIterator();
+ }
+
+ @Override
+ public void forEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ if(containsNull) action.accept(new BasicEntryKV_BRACES(keys[nullIndex], values[nullIndex]));
+ for(int i = nullIndex-1;i>=0;i--)
+ if(!strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(new BasicEntryKV_BRACES(keys[i], values[i]));
+ }
+
+ @Override
+ public void fastForEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
+ if(containsNull) {
+ entry.set(keys[nullIndex], values[nullIndex]);
+ action.accept(entry);
+ }
+ for(int i = nullIndex-1;i>=0;i--) {
+ if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) {
+ entry.set(keys[i], values[i]);
+ action.accept(entry);
+ }
+ }
+ }
+
+ @Override
+ public int size() {
+ return CUSTOM_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ CUSTOM_HASH_MAP.this.clear();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) return CUSTOM_HASH_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
+ return CUSTOM_HASH_MAP.this.containsKey(((Map.Entry, ?>)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return CUSTOM_HASH_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return CUSTOM_HASH_MAP.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+ }
+
+ private final class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE {
+#if TYPE_OBJECT
+ @Override
+ public boolean contains(Object e) {
+ return containsKey(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#else
+ @Override
+ public boolean contains(KEY_TYPE e) {
+ return containsKey(e);
+ }
+
+ @Override
+ public boolean remove(KEY_TYPE o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#endif
+ @Override
+ public boolean add(KEY_TYPE o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ITERATOR KEY_GENERIC_TYPE iterator() {
+ return new KeyIterator();
+ }
+
+ @Override
+ public int size() {
+ return CUSTOM_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ CUSTOM_HASH_MAP.this.clear();
+ }
+
+#if TYPE_OBJECT
+ @Override
+ public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) {
+ if(containsNull) action.accept(keys[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--)
+ if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(keys[i]);
+ }
+
+#else
+ @Override
+ public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
+ if(containsNull) action.accept(keys[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--)
+ if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(keys[i]);
+ }
+#endif
+ }
+
+ private class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+#if VALUE_OBJECT
+ @Override
+ public boolean contains(Object e) {
+ return containsValue(e);
+ }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) {
+ return containsValue(e);
+ }
+
+#endif
+ @Override
+ public boolean add(VALUE_TYPE o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
+ return new ValueIterator();
+ }
+
+ @Override
+ public int size() {
+ return CUSTOM_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ CUSTOM_HASH_MAP.this.clear();
+ }
+
+#if VALUE_OBJECT
+ @Override
+ public void forEach(Consumer VALUE_SUPER_GENERIC_TYPE action) {
+ if(containsNull) action.accept(values[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--)
+ if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(values[i]);
+ }
+#else
+ @Override
+ public void forEach(VALUE_CONSUMER VALUE_SUPER_GENERIC_TYPE action) {
+ if(containsNull) action.accept(values[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--)
+ if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(values[i]);
+ }
+#endif
+ }
+
+ private class FastEntryIterator extends MapIterator implements ObjectIterator {
+ MapEntry entry = new MapEntry();
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ entry.index = nextEntry();
+ return entry;
+ }
+ }
+
+ private class EntryIterator extends MapIterator implements ObjectIterator {
+ MapEntry entry;
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ return entry = new MapEntry(nextEntry());
+ }
+
+ @Override
+ public void remove() {
+ super.remove();
+ entry.index = -1;
+ }
+ }
+
+ private class KeyIterator extends MapIterator implements ITERATOR KEY_GENERIC_TYPE {
+ @Override
+ public KEY_TYPE NEXT() {
+ return keys[nextEntry()];
+ }
+ }
+
+ private class ValueIterator extends MapIterator implements VALUE_ITERATOR VALUE_GENERIC_TYPE {
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return values[nextEntry()];
+ }
+ }
+
+ private class MapIterator {
+ int pos = nullIndex;
+ int lastReturned = -1;
+ int nextIndex = Integer.MIN_VALUE;
+ boolean returnNull = containsNull;
+ LIST KEY_GENERIC_TYPE wrapped = null;
+
+ public boolean hasNext() {
+ if(nextIndex == Integer.MIN_VALUE) {
+ if(returnNull) {
+ returnNull = false;
+ nextIndex = nullIndex;
+ }
+ else
+ {
+ while(true) {
+ if(--pos < 0) {
+ if(wrapped == null || wrapped.size() <= -pos - 1) break;
+ nextIndex = -pos - 1;
+ break;
+ }
+ if(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)){
+ nextIndex = pos;
+ break;
+ }
+ }
+ }
+ }
+ return nextIndex != Integer.MIN_VALUE;
+ }
+
+ public int nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ if(nextIndex < 0){
+ lastReturned = Integer.MAX_VALUE;
+ int value = findIndex(wrapped.GET_KEY(nextIndex));
+ if(value < 0) throw new IllegalStateException("Entry ["+nextIndex+"] was removed during Iteration");
+ nextIndex = Integer.MIN_VALUE;
+ return value;
+ }
+ int value = (lastReturned = nextIndex);
+ nextIndex = Integer.MIN_VALUE;
+ return value;
+ }
+
+ public void remove() {
+ if(lastReturned == -1) throw new IllegalStateException();
+ if(lastReturned == nullIndex) {
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ }
+ else if(pos >= 0) shiftKeys(pos);
+ else {
+ CUSTOM_HASH_MAP.this.remove(wrapped.GET_KEY(-pos - 1));
+ return;
+ }
+ size--;
+ lastReturned = -1;
+ }
+
+ private void shiftKeys(int startPos) {
+ int slot, last;
+ KEY_TYPE current;
+ while(true) {
+ startPos = ((last = startPos) + 1) & mask;
+ while(true){
+ if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
+ keys[last] = EMPTY_KEY_VALUE;
+ values[last] = EMPTY_VALUE;
+ return;
+ }
+ slot = HashUtil.mix(strategy.hashCode(current)) & mask;
+ if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
+ startPos = ++startPos & mask;
+ }
+ if(startPos < last) {
+ if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
+ wrapped.add(keys[startPos]);
+ }
+ keys[last] = current;
+ values[last] = values[startPos];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/impl/hash/LinkedOpenHashMap.template b/src/main/resources/speiger/assets/collections/templates/maps/impl/hash/LinkedOpenHashMap.template
new file mode 100644
index 0000000..e912866
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/impl/hash/LinkedOpenHashMap.template
@@ -0,0 +1,1001 @@
+package speiger.src.collections.PACKAGE.maps.impl.hash;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.function.Consumer;
+#if TYPE_OBJECT
+import java.util.Objects;
+#endif
+
+import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.functions.COMPARATOR;
+import speiger.src.collections.PACKAGE.functions.CONSUMER;
+#endif
+import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
+import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
+import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.SORTED_MAP;
+import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
+import speiger.src.collections.PACKAGE.sets.SORTED_SET;
+import speiger.src.collections.PACKAGE.sets.SET;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
+#if !VALUE_OBJECT && !SAME_TYPE
+import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER;
+import speiger.src.collections.VALUE_PACKAGE.lists.VALUE_LIST_ITERATOR;
+#endif
+#if !TYPE_OBJECT
+import speiger.src.collections.objects.collections.ObjectBidirectionalIterator;
+import speiger.src.collections.objects.lists.ObjectListIterator;
+import speiger.src.collections.objects.sets.AbstractObjectSet;
+import speiger.src.collections.objects.sets.ObjectSortedSet;
+import speiger.src.collections.objects.sets.ObjectSet;
+#endif
+import speiger.src.collections.utils.HashUtil;
+
+public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_GENERIC_TYPE implements SORTED_MAP KEY_VALUE_GENERIC_TYPE
+{
+ protected long[] links;
+ protected int firstIndex = -1;
+ protected int lastIndex = -1;
+
+ public LINKED_HASH_MAP() {
+ this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public LINKED_HASH_MAP(int minCapacity) {
+ this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public LINKED_HASH_MAP(int minCapacity, float loadFactor) {
+ super(minCapacity, loadFactor);
+ links = new long[nullIndex + 1];
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ public LINKED_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values) {
+ this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public LINKED_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, float loadFactor) {
+ this(keys.length, loadFactor);
+ if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
+ for(int i = 0,m=keys.length;i map) {
+ this(map, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public LINKED_HASH_MAP(Map extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, float loadFactor) {
+ this(map.size(), loadFactor);
+ putAll(map);
+ }
+
+ public LINKED_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map) {
+ this(map, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public LINKED_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, float loadFactor) {
+ this(map.size(), loadFactor);
+ putAll(map);
+ }
+
+ @Override
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) {
+ if(KEY_EQUALS_NULL(key)) {
+ if(containsNull) {
+ VALUE_TYPE lastValue = values[nullIndex];
+ values[nullIndex] = value;
+ moveToFirstIndex(nullIndex);
+ return lastValue;
+ }
+ values[nullIndex] = value;
+ containsNull = true;
+ onNodeAdded(nullIndex);
+ }
+ else {
+ int pos = HashUtil.mix(KEY_TO_HASH(key)) & mask;
+ while(KEY_EQUALS_NOT_NULL(keys[pos])) {
+ if(KEY_EQUALS(keys[pos], key)) {
+ VALUE_TYPE lastValue = values[pos];
+ values[pos] = value;
+ moveToFirstIndex(pos);
+ return lastValue;
+ }
+ pos = ++pos & mask;
+ }
+ keys[pos] = key;
+ values[pos] = value;
+ onNodeAdded(pos);
+ }
+ if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) {
+ if(KEY_EQUALS_NULL(key)) {
+ if(containsNull) {
+ VALUE_TYPE lastValue = values[nullIndex];
+ values[nullIndex] = value;
+ moveToLastIndex(nullIndex);
+ return lastValue;
+ }
+ values[nullIndex] = value;
+ containsNull = true;
+ onNodeAdded(nullIndex);
+ }
+ else {
+ int pos = HashUtil.mix(KEY_TO_HASH(key)) & mask;
+ while(KEY_EQUALS_NOT_NULL(keys[pos])) {
+ if(KEY_EQUALS(keys[pos], key)) {
+ VALUE_TYPE lastValue = values[pos];
+ values[pos] = value;
+ moveToLastIndex(pos);
+ return lastValue;
+ }
+ pos = ++pos & mask;
+ }
+ keys[pos] = key;
+ values[pos] = value;
+ onNodeAdded(pos);
+ }
+ if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public boolean moveToFirst(KEY_TYPE key) {
+ if(KEY_EQUALS(FIRST_ENTRY_KEY(), key)) return false;
+ if(KEY_EQUALS_NULL(key)) {
+ if(containsNull) {
+ moveToFirstIndex(nullIndex);
+ return true;
+ }
+ }
+ else {
+ int pos = HashUtil.mix(KEY_TO_HASH(key)) & mask;
+ while(KEY_EQUALS_NOT_NULL(keys[pos])) {
+ if(KEY_EQUALS(keys[pos], key)) {
+ moveToFirstIndex(pos);
+ return true;
+ }
+ pos = ++pos & mask;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean moveToLast(KEY_TYPE key) {
+ if(KEY_EQUALS(LAST_ENTRY_KEY(), key)) return false;
+ if(KEY_EQUALS_NULL(key)) {
+ if(containsNull) {
+ moveToLastIndex(nullIndex);
+ return true;
+ }
+ }
+ else {
+ int pos = HashUtil.mix(KEY_TO_HASH(key)) & mask;
+ while(KEY_EQUALS_NOT_NULL(keys[pos])) {
+ if(KEY_EQUALS(keys[pos], key)) {
+ moveToLastIndex(pos);
+ return true;
+ }
+ pos = ++pos & mask;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index < 0) return getDefaultReturnValue();
+ moveToFirstIndex(index);
+ return values[index];
+ }
+
+ @Override
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index < 0) return getDefaultReturnValue();
+ moveToLastIndex(index);
+ return values[index];
+ }
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() {
+ return null;
+ }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public KEY_TYPE FIRST_ENTRY_KEY() {
+ if(size == 0) throw new NoSuchElementException();
+ return keys[firstIndex];
+ }
+
+ @Override
+ 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;
+ KEY_TYPE result = keys[pos];
+ size--;
+ if(KEY_EQUALS_NULL(result)) {
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ }
+ else shiftKeys(pos);
+ if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
+ return result;
+ }
+
+ @Override
+ public KEY_TYPE LAST_ENTRY_KEY() {
+ if(size == 0) throw new NoSuchElementException();
+ return keys[lastIndex];
+ }
+
+ @Override
+ 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;
+ KEY_TYPE result = keys[pos];
+ size--;
+ if(KEY_EQUALS_NULL(result)) {
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ }
+ else shiftKeys(pos);
+ if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
+ return result;
+ }
+
+ @Override
+ public VALUE_TYPE FIRST_ENTRY_VALUE() {
+ if(size == 0) throw new NoSuchElementException();
+ return values[firstIndex];
+ }
+
+ @Override
+ public VALUE_TYPE LAST_ENTRY_VALUE() {
+ if(size == 0) throw new NoSuchElementException();
+ return values[lastIndex];
+ }
+
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new MapEntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet() {
+ if(keySet == null) keySet = new KeySet();
+ return keySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(values == null) valuesC = new Values();
+ return valuesC;
+ }
+
+ @Override
+ public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(keys[index], values[index]);
+ index = (int)links[index];
+ }
+ }
+
+ @Override
+ public void clear() {
+ super.clear();
+ firstIndex = lastIndex = -1;
+ }
+
+ protected void moveToFirstIndex(int startPos) {
+ if(size == 1 || firstIndex == startPos) return;
+ if(lastIndex == startPos) {
+ lastIndex = (int)(links[startPos] >>> 32);
+ links[lastIndex] |= 0xFFFFFFFFL;
+ }
+ else {
+ long link = links[startPos];
+ int prev = (int)(link >>> 32);
+ int next = (int)link;
+ links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
+ }
+ links[firstIndex] ^= ((links[firstIndex] ^ ((startPos & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ links[startPos] = 0xFFFFFFFF00000000L | (firstIndex & 0xFFFFFFFFL);
+ firstIndex = startPos;
+ }
+
+ protected void moveToLastIndex(int startPos) {
+ if(size == 1 || lastIndex == startPos) return;
+ if(firstIndex == startPos) {
+ firstIndex = (int)links[startPos];
+ links[lastIndex] |= 0xFFFFFFFF00000000L;
+ }
+ else {
+ long link = links[startPos];
+ int prev = (int)(link >>> 32);
+ int next = (int)link;
+ links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
+ }
+ links[lastIndex] ^= ((links[lastIndex] ^ (startPos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[startPos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
+ lastIndex = startPos;
+ }
+
+ @Override
+ protected void onNodeAdded(int pos) {
+ if(size == 0) {
+ firstIndex = lastIndex = pos;
+ links[pos] = -1L;
+ }
+ else {
+ links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
+ lastIndex = pos;
+ }
+ }
+
+ @Override
+ protected void onNodeRemoved(int pos) {
+ if(size == 0) firstIndex = lastIndex = -1;
+ else if(firstIndex == pos) {
+ firstIndex = (int)links[pos];
+ if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
+ }
+ else if(lastIndex == pos) {
+ lastIndex = (int)(links[pos] >>> 32);
+ if(0 <= lastIndex) links[pos] |= 0xFFFFFFFFL;
+ }
+ else {
+ long link = links[pos];
+ int prev = (int)(link >>> 32);
+ int next = (int)link;
+ links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
+ }
+ }
+
+ @Override
+ protected void onNodeMoved(int from, int to) {
+ if(size == 1) {
+ firstIndex = lastIndex = to;
+ links[to] = -1L;
+ }
+ else if(firstIndex == from) {
+ firstIndex = to;
+ links[(int)links[from]] ^= ((links[(int)links[from]] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ links[to] = links[from];
+ }
+ else if(lastIndex == from) {
+ lastIndex = to;
+ links[(int)(links[from] >>> 32)] ^= ((links[(int)(links[from] >>> 32)] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[to] = links[from];
+ }
+ else {
+ long link = links[from];
+ int prev = (int)(link >>> 32);
+ int next = (int)link;
+ links[prev] ^= ((links[prev] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ links[next] ^= ((links[next] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ links[to] = link;
+ }
+ }
+
+ @Override
+ protected void rehash(int newSize) {
+ int newMask = newSize - 1;
+ KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
+ VALUE_TYPE[] newValues = NEW_VALUE_ARRAY(newSize + 1);
+ long[] newLinks = new long[newSize + 1];
+ int newPrev = -1;
+ for(int j = size, i = firstIndex, pos = 0, prev = -1;j != 0;) {
+ if(KEY_EQUALS_NULL(keys[i])) pos = newSize;
+ else {
+ pos = HashUtil.mix(KEY_TO_HASH(keys[i])) & newMask;
+ while(KEY_EQUALS_NOT_NULL(newKeys[pos])) pos = ++pos & newMask;
+ }
+ newKeys[pos] = keys[i];
+ newValues[pos] = values[i];
+ if(prev != -1) {
+ newLinks[newPrev] ^= ((newLinks[newPrev] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+ newLinks[pos] ^= ((newLinks[pos] ^ ((newPrev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ newPrev = pos;
+ }
+ else {
+ newPrev = firstIndex = pos;
+ newLinks[pos] = -1L;
+ }
+ i = (int)links[prev = i];
+ }
+ links = newLinks;
+ lastIndex = newPrev;
+ if(newPrev != -1) newLinks[newPrev] |= 0xFFFFFFFFL;
+ nullIndex = newSize;
+ mask = newMask;
+ maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
+ keys = newKeys;
+ }
+
+ private class MapEntrySet extends AbstractObjectSet implements SORTED_MAP.FastSortedSet KEY_VALUE_GENERIC_TYPE {
+ @Override
+ public boolean addAndMoveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public boolean moveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
+ return LINKED_HASH_MAP.this.moveToFirst(o.ENTRY_KEY());
+ }
+
+ @Override
+ public boolean moveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
+ return LINKED_HASH_MAP.this.moveToLast(o.ENTRY_KEY());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE first() {
+ return new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE last() {
+ return new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirst() {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
+ POLL_FIRST_ENTRY_KEY();
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLast() {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
+ POLL_LAST_ENTRY_KEY();
+ return entry;
+ }
+
+ @Override
+ public ObjectBidirectionalIterator iterator() {
+ return new EntryIterator();
+ }
+
+ @Override
+ public ObjectBidirectionalIterator iterator(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) {
+ return new EntryIterator(fromElement.ENTRY_KEY());
+ }
+
+ @Override
+ public ObjectBidirectionalIterator fastIterator() {
+ return new FastEntryIterator();
+ }
+
+ @Override
+ public ObjectBidirectionalIterator fastIterator(KEY_TYPE fromElement) {
+ return new FastEntryIterator(fromElement);
+ }
+
+ @Override
+ public void forEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(new BasicEntryKV_BRACES(keys[index], values[index]));
+ index = (int)links[index];
+ }
+ }
+
+ @Override
+ public void fastForEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
+ int index = firstIndex;
+ while(index != -1){
+ entry.set(keys[index], values[index]);
+ action.accept(entry);
+ index = (int)links[index];
+ }
+ }
+
+ @Override
+ @Deprecated
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) return LINKED_HASH_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
+ return LINKED_HASH_MAP.this.containsKey(((Map.Entry, ?>)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return LINKED_HASH_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return LINKED_HASH_MAP.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return LINKED_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ LINKED_HASH_MAP.this.clear();
+ }
+
+ @Override
+ public Comparator comparator() {
+ return null;
+ }
+ @Override
+ public ObjectSortedSet subSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement, MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
+ @Override
+ public ObjectSortedSet headSet(MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
+ @Override
+ public ObjectSortedSet tailSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) { throw new UnsupportedOperationException(); }
+ }
+
+ private final class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
+#if TYPE_OBJECT
+ @Override
+ @Deprecated
+ public boolean contains(Object e) {
+ return containsKey(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#else
+ @Override
+ public boolean contains(KEY_TYPE e) {
+ return containsKey(e);
+ }
+
+ @Override
+ public boolean remove(KEY_TYPE o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#endif
+ @Override
+ public boolean add(KEY_TYPE o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public boolean moveToFirst(KEY_TYPE o) {
+ return LINKED_HASH_MAP.this.moveToFirst(o);
+ }
+
+ @Override
+ public boolean moveToLast(KEY_TYPE o) {
+ return LINKED_HASH_MAP.this.moveToLast(o);
+ }
+
+ @Override
+ public LIST_ITERATOR KEY_GENERIC_TYPE iterator() {
+ return new KeyIterator();
+ }
+
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
+ return new KeyIterator(fromElement);
+ }
+
+ @Override
+ public int size() {
+ return LINKED_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ LINKED_HASH_MAP.this.clear();
+ }
+
+ @Override
+ public KEY_TYPE FIRST_KEY() {
+ return FIRST_ENTRY_KEY();
+ }
+
+ @Override
+ public KEY_TYPE POLL_FIRST_KEY() {
+ return POLL_FIRST_ENTRY_KEY();
+ }
+
+ @Override
+ public KEY_TYPE LAST_KEY() {
+ return LAST_ENTRY_KEY();
+ }
+
+ @Override
+ public KEY_TYPE POLL_LAST_KEY() {
+ return POLL_LAST_ENTRY_KEY();
+ }
+
+#if TYPE_OBJECT
+ @Override
+ public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(keys[index]);
+ index = (int)links[index];
+ }
+ }
+
+#else
+ @Override
+ public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(keys[index]);
+ index = (int)links[index];
+ }
+ }
+
+#endif
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return null; }
+
+ @Override
+ public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { throw new UnsupportedOperationException(); }
+ }
+
+ private class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+#if VALUE_OBJECT
+ @Override
+ @Deprecated
+ public boolean contains(Object e) {
+ return containsValue(e);
+ }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) {
+ return containsValue(e);
+ }
+
+#endif
+ @Override
+ public boolean add(VALUE_TYPE o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
+ return new ValueIterator();
+ }
+
+ @Override
+ public int size() {
+ return LINKED_HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ LINKED_HASH_MAP.this.clear();
+ }
+
+#if VALUE_OBJECT
+ @Override
+ public void forEach(Consumer VALUE_SUPER_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(values[index]);
+ index = (int)links[index];
+ }
+ }
+#else
+ @Override
+ public void forEach(VALUE_CONSUMER VALUE_SUPER_GENERIC_TYPE action) {
+ int index = firstIndex;
+ while(index != -1){
+ action.accept(values[index]);
+ index = (int)links[index];
+ }
+ }
+#endif
+ }
+
+ private class FastEntryIterator extends MapIterator implements ObjectListIterator {
+ MapEntry entry = new MapEntry(nextEntry());
+
+ public FastEntryIterator() {}
+ public FastEntryIterator(KEY_TYPE from) {
+ super(from);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ entry.index = nextEntry();
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ entry.index = previousEntry();
+ return entry;
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
+ }
+
+ private class EntryIterator extends MapIterator implements ObjectListIterator {
+ MapEntry entry;
+
+ public EntryIterator() {}
+ public EntryIterator(KEY_TYPE from) {
+ super(from);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ return entry = new MapEntry(nextEntry());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ return entry = new MapEntry(previousEntry());
+ }
+
+ @Override
+ public void remove() {
+ super.remove();
+ entry.index = -1;
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
+ }
+
+ private class KeyIterator extends MapIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
+
+ public KeyIterator() {}
+ public KeyIterator(KEY_TYPE from) {
+ super(from);
+ }
+
+ @Override
+ public KEY_TYPE PREVIOUS() {
+ return keys[previousEntry()];
+ }
+
+ @Override
+ public KEY_TYPE NEXT() {
+ return keys[nextEntry()];
+ }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class ValueIterator extends MapIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
+ public ValueIterator() {}
+
+ @Override
+ public VALUE_TYPE VALUE_PREVIOUS() {
+ return values[previousEntry()];
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return values[nextEntry()];
+ }
+
+ @Override
+ public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+
+ }
+
+ private class MapIterator {
+ int previous = -1;
+ int next = -1;
+ int current = -1;
+ int index = 0;
+
+ MapIterator() {
+ next = firstIndex;
+ }
+
+ MapIterator(KEY_TYPE from) {
+ if(KEY_EQUALS_NULL(from)) {
+ if(containsNull) {
+ next = (int) links[nullIndex];
+ previous = nullIndex;
+ }
+ else throw new NoSuchElementException("The null element is not in the set");
+ }
+ else if(keys[lastIndex] == from) {
+ previous = lastIndex;
+ index = size;
+ }
+ else {
+ int pos = HashUtil.mix(KEY_TO_HASH(from)) & mask;
+ while(KEY_EQUALS_NOT_NULL(keys[pos])) {
+ if(KEY_EQUALS(keys[pos], from)) {
+ next = (int)links[pos];
+ previous = pos;
+ break;
+ }
+ pos = ++pos & mask;
+ }
+ if(previous == -1 && next == -1)
+ throw new NoSuchElementException("The element was not found");
+ }
+ }
+
+ public boolean hasNext() {
+ return next != -1;
+ }
+
+ public boolean hasPrevious() {
+ return previous != -1;
+ }
+
+ public int nextIndex() {
+ ensureIndexKnown();
+ return index;
+ }
+
+ public int previousIndex() {
+ ensureIndexKnown();
+ return index - 1;
+ }
+
+ public void remove() {
+ if(current == -1) throw new IllegalStateException();
+ ensureIndexKnown();
+ if(current == previous) {
+ index--;
+ previous = (int)(links[current] >>> 32);
+ }
+ else next = (int)links[current];
+ size--;
+ if(previous == -1) firstIndex = next;
+ else links[previous] ^= ((links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
+
+ if (next == -1) lastIndex = previous;
+ else links[next] ^= ((links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
+ if(current == nullIndex) {
+ current = -1;
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ }
+ else {
+ int slot, last, startPos = current;
+ current = -1;
+ KEY_TYPE current;
+ while(true) {
+ startPos = ((last = startPos) + 1) & mask;
+ while(true){
+ if(KEY_EQUALS_NULL((current = keys[startPos]))) {
+ keys[last] = EMPTY_KEY_VALUE;
+ values[last] = EMPTY_VALUE;
+ return;
+ }
+ slot = HashUtil.mix(KEY_TO_HASH(current)) & mask;
+ if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
+ startPos = ++startPos & mask;
+ }
+ keys[last] = current;
+ values[last] = values[startPos];
+ if(next == startPos) next = last;
+ if(previous == startPos) previous = last;
+ onNodeMoved(startPos, last);
+ }
+ }
+ }
+
+ public int previousEntry() {
+ if(!hasPrevious()) throw new NoSuchElementException();
+ current = previous;
+ previous = (int)(links[current] >> 32);
+ next = current;
+ if(index >= 0) index--;
+ return current;
+ }
+
+ public int nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ current = next;
+ next = (int)(links[current]);
+ previous = current;
+ if(index >= 0) index++;
+ return current;
+ }
+
+ private void ensureIndexKnown() {
+ if(index == -1) {
+ if(previous == -1) {
+ index = 0;
+ }
+ else if(next == -1) {
+ index = size;
+ }
+ else {
+ index = 1;
+ for(int pos = firstIndex;pos != previous;pos = (int)links[pos], index++);
+ }
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template b/src/main/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template
new file mode 100644
index 0000000..06b9b27
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template
@@ -0,0 +1,776 @@
+package speiger.src.collections.PACKAGE.maps.impl.hash;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.collections.ITERATOR;
+import speiger.src.collections.PACKAGE.functions.CONSUMER;
+#endif
+import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
+import speiger.src.collections.PACKAGE.lists.ARRAY_LIST;
+import speiger.src.collections.PACKAGE.lists.LIST;
+import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
+import speiger.src.collections.PACKAGE.sets.SET;
+#endif
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+#if !SAME_TYPE && !VALUE_OBJECT
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
+import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER;
+#endif
+import speiger.src.collections.objects.collections.ObjectIterator;
+import speiger.src.collections.objects.sets.AbstractObjectSet;
+import speiger.src.collections.objects.sets.ObjectSet;
+import speiger.src.collections.utils.HashUtil;
+
+public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE
+{
+ protected transient KEY_TYPE[] keys;
+ protected transient VALUE_TYPE[] values;
+ protected transient boolean containsNull;
+ protected transient int minCapacity;
+ protected transient int nullIndex;
+ protected transient int maxFill;
+ protected transient int mask;
+ protected transient FastEntrySet KEY_VALUE_GENERIC_TYPE entrySet;
+ protected transient SET KEY_GENERIC_TYPE keySet;
+ protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC;
+
+ protected int size;
+ protected final float loadFactor;
+
+ public HASH_MAP() {
+ this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public HASH_MAP(int minCapacity) {
+ this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public HASH_MAP(int minCapacity, float loadFactor) {
+ if(minCapacity < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed");
+ if(loadFactor <= 0 || loadFactor >= 1F) throw new IllegalStateException("Load Factor is not between 0 and 1");
+ this.loadFactor = loadFactor;
+ this.minCapacity = nullIndex = HashUtil.arraySize(minCapacity, loadFactor);
+ mask = nullIndex - 1;
+ maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
+ keys = NEW_KEY_ARRAY(nullIndex + 1);
+ values = NEW_VALUE_ARRAY(nullIndex + 1);
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ public HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values) {
+ this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, float loadFactor) {
+ this(keys.length, loadFactor);
+ if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
+ for(int i = 0,m=keys.length;i map) {
+ this(map, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public HASH_MAP(Map extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, float loadFactor) {
+ this(map.size(), loadFactor);
+ putAll(map);
+ }
+
+ public HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map) {
+ this(map, HashUtil.DEFAULT_LOAD_FACTOR);
+ }
+
+ public HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, float loadFactor) {
+ this(map.size(), loadFactor);
+ putAll(map);
+ }
+
+ @Override
+ public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
+ int slot = findIndex(key);
+ if(slot < 0) {
+ insert(-slot-1, key, value);
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE oldValue = values[slot];
+ values[slot] = value;
+ return oldValue;
+ }
+
+ @Override
+ public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
+ int slot = findIndex(key);
+ if(slot < 0) {
+ insert(-slot-1, key, value);
+ return getDefaultReturnValue();
+ }
+ return values[slot];
+ }
+
+#if VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
+ int slot = findIndex(key);
+ if(slot < 0) {
+ insert(-slot-1, key, value);
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE oldValue = values[slot];
+ values[slot] += value;
+ return oldValue;
+ }
+
+#endif
+#if !TYPE_OBJECT
+ @Override
+ public boolean containsKey(KEY_TYPE key) {
+ return findIndex(key) >= 0;
+ }
+
+#endif
+ @Override
+ @Deprecated
+ public boolean containsKey(Object key) {
+ return findIndex(key) >= 0;
+ }
+
+#if !VALUE_OBJECT
+ @Override
+ public boolean containsValue(VALUE_TYPE value) {
+ if(VALUE_EQUALS(value, values[nullIndex])) return true;
+ for(int i = nullIndex-1;i >= 0;i--)
+ if(KEY_EQUALS_NOT_NULL(keys[i]) && VALUE_EQUALS(values[i], value)) return true;
+ return false;
+ }
+
+#endif
+ @Override
+ @Deprecated
+ public boolean containsValue(Object value) {
+ if((value == null && VALUE_EQUALS(values[nullIndex], getDefaultReturnValue())) || EQUALS_VALUE_TYPE(values[nullIndex], value)) return true;
+ for(int i = nullIndex-1;i >= 0;i--)
+ if(KEY_EQUALS_NOT_NULL(keys[i]) && ((value == null && values[i] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[i], value))) return true;
+ return false;
+ }
+
+ @Override
+ public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
+ int slot = findIndex(key);
+ if(slot < 0) return getDefaultReturnValue();
+ return removeIndex(slot);
+ }
+
+ @Override
+ @Deprecated
+ public CLASS_VALUE_TYPE remove(Object key) {
+ int slot = findIndex(key);
+ if(slot < 0) return VALUE_TO_OBJ(getDefaultReturnValue());
+ return removeIndex(slot);
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ @Override
+ public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
+ if(KEY_EQUALS_NULL(key)) {
+ if(containsNull && VALUE_EQUALS(value, values[nullIndex])) {
+ removeNullIndex();
+ return true;
+ }
+ return false;
+ }
+ int pos = HashUtil.mix(KEY_TO_HASH(key)) & mask;
+ KEY_TYPE current = keys[pos];
+ if(KEY_EQUALS_NULL(current)) return false;
+ if(KEY_EQUALS(current, key) && VALUE_EQUALS(value, values[pos])) {
+ removeIndex(pos);
+ return true;
+ }
+ while(true) {
+ if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
+ else if(KEY_EQUALS(current, key) && VALUE_EQUALS(value, values[pos])) {
+ removeIndex(pos);
+ return true;
+ }
+ }
+ }
+
+#endif
+ @Override
+ public boolean remove(Object key, Object value) {
+ Objects.requireNonNull(value);
+ if(key == null) {
+ if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
+ removeNullIndex();
+ return true;
+ }
+ return false;
+ }
+ int pos = HashUtil.mix(key.hashCode()) & mask;
+ KEY_TYPE current = keys[pos];
+ if(KEY_EQUALS_NULL(current)) return false;
+ if(EQUALS_KEY_TYPE(current, key) && EQUALS_VALUE_TYPE(values[pos], value)) {
+ removeIndex(pos);
+ return true;
+ }
+ while(true) {
+ if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
+ else if(EQUALS_KEY_TYPE(current, key) && EQUALS_VALUE_TYPE(values[pos], value)){
+ removeIndex(pos);
+ return true;
+ }
+ }
+ }
+
+ @Override
+ public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
+ int slot = findIndex(key);
+ return slot < 0 ? getDefaultReturnValue() : values[slot];
+ }
+
+ @Override
+ public CLASS_VALUE_TYPE get(Object key) {
+ int slot = findIndex(key);
+ return VALUE_TO_OBJ(slot < 0 ? getDefaultReturnValue() : values[slot]);
+ }
+
+#if !TYPE_OBJECT
+ @Override
+ public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
+ int slot = findIndex(key);
+ return slot < 0 ? defaultValue : values[slot];
+ }
+
+#endif
+ @Override
+ public CLASS_VALUE_TYPE getOrDefault(Object key, CLASS_VALUE_TYPE defaultValue) {
+ int slot = findIndex(key);
+ return slot < 0 ? defaultValue : VALUE_TO_OBJ(values[slot]);
+ }
+
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new MapEntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet() {
+ if(keySet == null) keySet = new KeySet();
+ return keySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(valuesC == null) valuesC = new Values();
+ return valuesC;
+ }
+
+ @Override
+ public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
+ if(size() <= 0) return;
+ if(containsNull) action.accept(keys[nullIndex], values[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--) {
+ if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(keys[i], values[i]);
+ }
+ }
+
+ @Override
+ public void clear() {
+ if(size == 0) return;
+ size = 0;
+ containsNull = false;
+ Arrays.fill(keys, EMPTY_KEY_VALUE);
+ Arrays.fill(values, EMPTY_VALUE);
+ }
+
+#if !TYPE_OBJECT
+ protected int findIndex(KEY_TYPE key) {
+ if(KEY_EQUALS_NULL(key)) return containsNull ? nullIndex : -(nullIndex + 1);
+ int pos = HashUtil.mix(KEY_TO_HASH(key)) & mask;
+ KEY_TYPE current = keys[pos];
+ if(KEY_EQUALS_NOT_NULL(current)) {
+ if(KEY_EQUALS(current, key)) return pos;
+ while(KEY_EQUALS_NOT_NULL((current = keys[pos = (++pos & mask)])))
+ if(KEY_EQUALS(current, key)) return pos;
+ }
+ return -(pos + 1);
+ }
+
+#endif
+ protected int findIndex(Object key) {
+ if(key == null) return containsNull ? nullIndex : -(nullIndex + 1);
+ int pos = HashUtil.mix(key.hashCode()) & mask;
+ KEY_TYPE current = keys[pos];
+ if(KEY_EQUALS_NOT_NULL(current)) {
+ if(EQUALS_KEY_TYPE(current, key)) return pos;
+ while(KEY_EQUALS_NOT_NULL((current = keys[pos = (++pos & mask)])))
+ if(EQUALS_KEY_TYPE(current, key)) return pos;
+ }
+ return -(pos + 1);
+ }
+
+ protected VALUE_TYPE removeIndex(int pos) {
+ VALUE_TYPE value = values[pos];
+ size--;
+ onNodeRemoved(pos);
+ shiftKeys(pos);
+ if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
+ return value;
+ }
+
+ protected VALUE_TYPE removeNullIndex() {
+ VALUE_TYPE value = values[nullIndex];
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ size--;
+ onNodeRemoved(nullIndex);
+ if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
+ return value;
+ }
+
+ protected void insert(int slot, KEY_TYPE key, VALUE_TYPE value) {
+ if(slot == nullIndex) containsNull = true;
+ keys[slot] = key;
+ values[slot] = value;
+ onNodeAdded(slot);
+ if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
+ }
+
+ protected void rehash(int newSize) {
+ int newMask = newSize - 1;
+ KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
+ VALUE_TYPE[] newValues = NEW_VALUE_ARRAY(newSize + 1);
+ for(int i = nullIndex, pos = 0, j = (size - (containsNull ? 1 : 0));j-- != 0;) {
+ while(KEY_EQUALS_NULL(keys[--i]));
+ if(KEY_EQUALS_NOT_NULL(newKeys[pos = HashUtil.mix(KEY_TO_HASH(keys[i])) & newMask]))
+ while(KEY_EQUALS_NOT_NULL(newKeys[pos = (++pos & newMask)]));
+ newKeys[pos] = keys[i];
+ newValues[pos] = values[i];
+ }
+ newValues[newSize] = values[nullIndex];
+ nullIndex = newSize;
+ mask = newMask;
+ maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
+ keys = newKeys;
+ values = newValues;
+ }
+
+ protected void onNodeAdded(int pos) {
+
+ }
+
+ protected void onNodeRemoved(int pos) {
+
+ }
+
+ protected void onNodeMoved(int from, int to) {
+
+ }
+
+ protected void shiftKeys(int startPos) {
+ int slot, last;
+ KEY_TYPE current;
+ while(true) {
+ startPos = ((last = startPos) + 1) & mask;
+ while(true){
+ if(KEY_EQUALS_NULL((current = keys[startPos]))) {
+ keys[last] = EMPTY_KEY_VALUE;
+ values[last] = EMPTY_VALUE;
+ return;
+ }
+ slot = HashUtil.mix(KEY_TO_HASH(current)) & mask;
+ if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
+ startPos = ++startPos & mask;
+ }
+ keys[last] = current;
+ values[last] = values[startPos];
+ onNodeMoved(startPos, last);
+ }
+ }
+
+ protected class MapEntry implements MAP.Entry KEY_VALUE_GENERIC_TYPE, Map.Entry {
+ public int index = -1;
+
+ public MapEntry() {}
+ public MapEntry(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public KEY_TYPE ENTRY_KEY() {
+ return keys[index];
+ }
+
+ @Override
+ public VALUE_TYPE ENTRY_VALUE() {
+ return values[index];
+ }
+
+ @Override
+ public VALUE_TYPE setValue(VALUE_TYPE value) {
+ VALUE_TYPE oldValue = values[index];
+ values[index] = value;
+ return oldValue;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(obj instanceof Map.Entry) {
+ if(obj instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)obj;
+ return KEY_EQUALS(keys[index], entry.ENTRY_KEY()) && VALUE_EQUALS(values[index], entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)obj;
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+#if TYPE_OBJECT && VALUE_OBJECT
+ return KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], value);
+#else if TYPE_OBJECT
+ return value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
+#else if VALUE_OBJECT
+ return key instanceof CLASS_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], value);
+#else
+ return key instanceof CLASS_TYPE && value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
+#endif
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return KEY_TO_HASH(keys[index]) ^ VALUE_TO_HASH(values[index]);
+ }
+
+ @Override
+ public String toString() {
+ return KEY_TO_STRING(keys[index]) + "->" + VALUE_TO_STRING(values[index]);
+ }
+ }
+
+ private final class MapEntrySet extends AbstractObjectSet implements MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE {
+ @Override
+ public ObjectIterator fastIterator() {
+ return new FastEntryIterator();
+ }
+
+ @Override
+ public ObjectIterator iterator() {
+ return new EntryIterator();
+ }
+
+ @Override
+ public void forEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ if(containsNull) action.accept(new BasicEntryKV_BRACES(keys[nullIndex], values[nullIndex]));
+ for(int i = nullIndex-1;i>=0;i--)
+ if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(new BasicEntryKV_BRACES(keys[i], values[i]));
+ }
+
+ @Override
+ public void fastForEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
+ if(containsNull) {
+ entry.set(keys[nullIndex], values[nullIndex]);
+ action.accept(entry);
+ }
+ for(int i = nullIndex-1;i>=0;i--) {
+ if(KEY_EQUALS_NOT_NULL(keys[i])) {
+ entry.set(keys[i], values[i]);
+ action.accept(entry);
+ }
+ }
+ }
+
+ @Override
+ public int size() {
+ return HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ HASH_MAP.this.clear();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) return HASH_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
+ return HASH_MAP.this.containsKey(((Map.Entry, ?>)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return HASH_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return HASH_MAP.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+ }
+
+ private final class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE {
+#if TYPE_OBJECT
+ @Override
+ public boolean contains(Object e) {
+ return containsKey(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#else
+ @Override
+ public boolean contains(KEY_TYPE e) {
+ return containsKey(e);
+ }
+
+ @Override
+ public boolean remove(KEY_TYPE o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#endif
+ @Override
+ public boolean add(KEY_TYPE o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ITERATOR KEY_GENERIC_TYPE iterator() {
+ return new KeyIterator();
+ }
+
+ @Override
+ public int size() {
+ return HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ HASH_MAP.this.clear();
+ }
+
+#if TYPE_OBJECT
+ @Override
+ public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) {
+ if(containsNull) action.accept(keys[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--)
+ if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(keys[i]);
+ }
+
+#else
+ @Override
+ public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
+ if(containsNull) action.accept(keys[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--)
+ if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(keys[i]);
+ }
+#endif
+ }
+
+ private class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+#if VALUE_OBJECT
+ @Override
+ public boolean contains(Object e) {
+ return containsValue(e);
+ }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) {
+ return containsValue(e);
+ }
+
+#endif
+ @Override
+ public boolean add(VALUE_TYPE o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
+ return new ValueIterator();
+ }
+
+ @Override
+ public int size() {
+ return HASH_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ HASH_MAP.this.clear();
+ }
+
+#if VALUE_OBJECT
+ @Override
+ public void forEach(Consumer VALUE_SUPER_GENERIC_TYPE action) {
+ if(containsNull) action.accept(values[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--)
+ if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(values[i]);
+ }
+#else
+ @Override
+ public void forEach(VALUE_CONSUMER VALUE_SUPER_GENERIC_TYPE action) {
+ if(containsNull) action.accept(values[nullIndex]);
+ for(int i = nullIndex-1;i>=0;i--)
+ if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(values[i]);
+ }
+#endif
+ }
+
+ private class FastEntryIterator extends MapIterator implements ObjectIterator {
+ MapEntry entry = new MapEntry();
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ entry.index = nextEntry();
+ return entry;
+ }
+ }
+
+ private class EntryIterator extends MapIterator implements ObjectIterator {
+ MapEntry entry;
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ return entry = new MapEntry(nextEntry());
+ }
+
+ @Override
+ public void remove() {
+ super.remove();
+ entry.index = -1;
+ }
+ }
+
+ private class KeyIterator extends MapIterator implements ITERATOR KEY_GENERIC_TYPE {
+ @Override
+ public KEY_TYPE NEXT() {
+ return keys[nextEntry()];
+ }
+ }
+
+ private class ValueIterator extends MapIterator implements VALUE_ITERATOR VALUE_GENERIC_TYPE {
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return values[nextEntry()];
+ }
+ }
+
+ private class MapIterator {
+ int pos = nullIndex;
+ int lastReturned = -1;
+ int nextIndex = Integer.MIN_VALUE;
+ boolean returnNull = containsNull;
+ LIST KEY_GENERIC_TYPE wrapped = null;
+
+ public boolean hasNext() {
+ if(nextIndex == Integer.MIN_VALUE) {
+ if(returnNull) {
+ returnNull = false;
+ nextIndex = nullIndex;
+ }
+ else
+ {
+ while(true) {
+ if(--pos < 0) {
+ if(wrapped == null || wrapped.size() <= -pos - 1) break;
+ nextIndex = -pos - 1;
+ break;
+ }
+ if(KEY_EQUALS_NOT_NULL(keys[pos])){
+ nextIndex = pos;
+ break;
+ }
+ }
+ }
+ }
+ return nextIndex != Integer.MIN_VALUE;
+ }
+
+ public int nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ if(nextIndex < 0){
+ lastReturned = Integer.MAX_VALUE;
+ int value = findIndex(wrapped.GET_KEY(nextIndex));
+ if(value < 0) throw new IllegalStateException("Entry ["+nextIndex+"] was removed during Iteration");
+ nextIndex = Integer.MIN_VALUE;
+ return value;
+ }
+ int value = (lastReturned = nextIndex);
+ nextIndex = Integer.MIN_VALUE;
+ return value;
+ }
+
+ public void remove() {
+ if(lastReturned == -1) throw new IllegalStateException();
+ if(lastReturned == nullIndex) {
+ containsNull = false;
+ keys[nullIndex] = EMPTY_KEY_VALUE;
+ values[nullIndex] = EMPTY_VALUE;
+ }
+ else if(pos >= 0) shiftKeys(pos);
+ else {
+ HASH_MAP.this.remove(wrapped.GET_KEY(-pos - 1));
+ return;
+ }
+ size--;
+ lastReturned = -1;
+ }
+
+ private void shiftKeys(int startPos) {
+ int slot, last;
+ KEY_TYPE current;
+ while(true) {
+ startPos = ((last = startPos) + 1) & mask;
+ while(true){
+ if(KEY_EQUALS_NULL((current = keys[startPos]))) {
+ keys[last] = EMPTY_KEY_VALUE;
+ values[last] = EMPTY_VALUE;
+ return;
+ }
+ slot = HashUtil.mix(KEY_TO_HASH(current)) & mask;
+ if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
+ startPos = ++startPos & mask;
+ }
+ if(startPos < last) {
+ if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
+ wrapped.add(keys[startPos]);
+ }
+ keys[last] = current;
+ values[last] = values[startPos];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/impl/misc/ArrayMap.template b/src/main/resources/speiger/assets/collections/templates/maps/impl/misc/ArrayMap.template
new file mode 100644
index 0000000..745c0bb
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/impl/misc/ArrayMap.template
@@ -0,0 +1,1653 @@
+package speiger.src.collections.PACKAGE.maps.impl.misc;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.functions.COMPARATOR;
+import speiger.src.collections.PACKAGE.functions.CONSUMER;
+#endif
+import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
+import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.SORTED_MAP;
+import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
+import speiger.src.collections.PACKAGE.sets.SORTED_SET;
+import speiger.src.collections.PACKAGE.sets.SET;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
+#if !SAME_TYPE && !VALUE_OBJECT
+import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER;
+import speiger.src.collections.VALUE_PACKAGE.lists.VALUE_LIST_ITERATOR;
+#endif
+#if !TYPE_OBJECT
+import speiger.src.collections.objects.collections.ObjectBidirectionalIterator;
+import speiger.src.collections.objects.lists.ObjectListIterator;
+import speiger.src.collections.objects.sets.AbstractObjectSet;
+import speiger.src.collections.objects.sets.ObjectSortedSet;
+import speiger.src.collections.objects.sets.ObjectSet;
+#endif
+
+public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements SORTED_MAP KEY_VALUE_GENERIC_TYPE
+{
+ protected transient KEY_TYPE[] keys;
+ protected transient VALUE_TYPE[] values;
+ protected int size = 0;
+ protected SET KEY_GENERIC_TYPE keySet;
+ protected VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC;
+ protected FastSortedSet KEY_VALUE_GENERIC_TYPE entrySet;
+
+ @Override
+ public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index < 0) {
+ insertIndex(size++, key, value);
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE oldValue = values[index];
+ values[index] = value;
+ return oldValue;
+ }
+
+ @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 VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index < 0) {
+ insertIndex(size++, key, value);
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE oldValue = values[index];
+ values[index] += value;
+ return oldValue;
+ }
+
+#endif
+ @Override
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index < 0) {
+ insertIndex(0, key, value);
+ size++;
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE lastValue = values[index];
+ values[index] = value;
+ moveIndexToFirst(index);
+ return lastValue;
+ }
+
+ @Override
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index < 0) {
+ insertIndex(size++, key, value);
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE lastValue = values[index];
+ values[index] = value;
+ moveIndexToLast(index);
+ return lastValue;
+ }
+
+ @Override
+ public boolean moveToFirst(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ moveIndexToFirst(index);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean moveToLast(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ moveIndexToLast(index);
+ return true;
+ }
+ return false;
+ }
+
+#if !TYPE_OBJECT
+ @Override
+ public boolean containsKey(KEY_TYPE key) {
+ return findIndex(key) >= 0;
+ }
+
+#endif
+#if !VALUE_OBJECT
+ @Override
+ public boolean containsValue(VALUE_TYPE value) {
+ return findValue(value) >= 0;
+ }
+
+#endif
+ @Override
+ public boolean containsKey(Object key) {
+ return findIndex(key) >= 0;
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return findValue(value) >= 0;
+ }
+
+ @Override
+ public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
+ int index = findIndex(key);
+ return index < 0 ? getDefaultReturnValue() : values[index];
+ }
+
+#if !TYPE_OBJECT
+ @Override
+ public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
+ int index = findIndex(key);
+ return index < 0 ? defaultValue : values[index];
+ }
+
+#endif
+ @Override
+ public CLASS_VALUE_TYPE getOrDefault(Object key, CLASS_VALUE_TYPE defaultValue) {
+ int index = findIndex(key);
+ return index < 0 ? defaultValue : VALUE_TO_OBJ(values[index]);
+ }
+
+ @Override
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ VALUE_TYPE value = values[index];
+ moveIndexToFirst(index);
+ return value;
+ }
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ VALUE_TYPE value = values[index];
+ moveIndexToLast(index);
+ return value;
+ }
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public KEY_TYPE FIRST_ENTRY_KEY() {
+ if(size <= 0) throw new NoSuchElementException();
+ return keys[0];
+ }
+
+ @Override
+ public KEY_TYPE LAST_ENTRY_KEY() {
+ if(size <= 0) throw new NoSuchElementException();
+ return keys[size-1];
+ }
+
+ @Override
+ public VALUE_TYPE FIRST_ENTRY_VALUE() {
+ if(size <= 0) throw new NoSuchElementException();
+ return values[size-1];
+ }
+
+ @Override
+ public VALUE_TYPE LAST_ENTRY_VALUE() {
+ if(size <= 0) throw new NoSuchElementException();
+ return values[0];
+ }
+
+ @Override
+ public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
+ if(size == 0) throw new NoSuchElementException();
+ KEY_TYPE result = keys[0];
+ removeIndex(0);
+ return result;
+ }
+
+ @Override
+ public KEY_TYPE POLL_LAST_ENTRY_KEY() {
+ if(size == 0) throw new NoSuchElementException();
+ KEY_TYPE result = keys[size-1];
+ removeIndex(size-1);
+ return result;
+ }
+
+ @Override
+ public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index < 0) return getDefaultReturnValue();
+ VALUE_TYPE value = values[index];
+ removeIndex(index);
+ return value;
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ @Override
+ public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key, value);
+ if(index < 0) return false;
+ removeIndex(index);
+ return true;
+ }
+
+#endif
+ @Override
+ public CLASS_VALUE_TYPE remove(Object key) {
+ int index = findIndex(key);
+ if(index < 0) return VALUE_TO_OBJ(getDefaultReturnValue());
+ VALUE_TYPE value = values[index];
+ removeIndex(index);
+ return VALUE_TO_OBJ(value);
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ int index = findIndex(key, value);
+ if(index < 0) return false;
+ removeIndex(index);
+ return true;
+ }
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet() {
+ if(keySet == null) keySet = new KeySet();
+ return keySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(valuesC == null) valuesC = new Values();
+ return valuesC;
+ }
+
+ @Override
+ public ObjectSortedSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new MapEntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public void clear() {
+ Arrays.fill(keys, 0, size, EMPTY_KEY_VALUE);
+ Arrays.fill(values, 0, size, EMPTY_VALUE);
+ size = 0;
+ }
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() {
+ return null;
+ }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey) {
+ int fromIndex = findIndex(fromKey);
+ int toIndex = findIndex(toKey);
+ if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException();
+ return new SubMap(fromIndex, toIndex - fromIndex + 1);
+ }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey) {
+ int toIndex = findIndex(toKey);
+ if(toIndex == -1) throw new NoSuchElementException();
+ return new SubMap(0, toIndex + 1);
+ }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey) {
+ int fromIndex = findIndex(fromKey);
+ if(fromIndex == -1) throw new NoSuchElementException();
+ return new SubMap(fromIndex, size - fromIndex);
+ }
+
+ protected void moveIndexToFirst(int index) {
+ if(index == 0) return;
+ KEY_TYPE key = keys[index];
+ VALUE_TYPE value = values[index];
+ System.arraycopy(keys, 0, keys, 1, index);
+ System.arraycopy(values, 0, values, 1, index);
+ keys[0] = key;
+ values[0] = value;
+ }
+
+ protected void moveIndexToLast(int index) {
+ if(index == size-1) return;
+ KEY_TYPE key = keys[index];
+ VALUE_TYPE value = values[index];
+ System.arraycopy(keys, index+1, keys, index, size-index-1);
+ System.arraycopy(values, index+1, values, index, size-index-1);
+ keys[size-1] = key;
+ values[size-1] = value;
+ }
+
+ protected void grow(int newSize) {
+ if(newSize < keys.length) return;
+ newSize = Math.min(newSize, keys.length == 0 ? 2 : keys.length * 2);
+ keys = Arrays.copyOf(keys, newSize);
+ values = Arrays.copyOf(values, newSize);
+ }
+
+ protected void insertIndex(int index, KEY_TYPE key, VALUE_TYPE value) {
+ grow(size+1);
+ if(index != size) {
+ System.arraycopy(keys, index, keys, index+1, size-index);
+ System.arraycopy(values, index, values, index+1, size-index);
+ }
+ keys[index] = key;
+ values[index] = value;
+ }
+
+ protected void removeRange(int from, int to) {
+ if(from < 0 || from >= size) throw new IllegalStateException("From Element ");
+ int length = to - from;
+ if(length <= 0) return;
+ if(to != size) {
+ System.arraycopy(keys, to, keys, from, size - to);
+ System.arraycopy(values, to, values, from, size - to);
+ }
+ for(int i = 0;i=0;i--)
+ if(KEY_EQUALS(keys[i], key) && VALUE_EQUALS(values[i], value)) return i;
+ return -1;
+ }
+
+#endif
+#if !TYPE_OBJECT
+ protected int findIndex(KEY_TYPE key) {
+ for(int i = size-1;i>=0;i--)
+ if(KEY_EQUALS(keys[i], key)) return i;
+ return -1;
+ }
+
+#endif
+#if !VALUE_OBJECT
+ protected int findValue(VALUE_TYPE value) {
+ for(int i = size-1;i>=0;i--)
+ if(VALUE_EQUALS(values[i], value)) return i;
+ return -1;
+ }
+
+#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;
+ }
+
+ private class SubMap extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements SORTED_MAP KEY_VALUE_GENERIC_TYPE {
+ int offset;
+ int length;
+
+ SET KEY_GENERIC_TYPE keySet;
+ VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC;
+ FastSortedSet KEY_VALUE_GENERIC_TYPE entrySet;
+
+ public SubMap(int offset, int length) {
+ this.offset = offset;
+ this.length = length;
+ }
+
+ int end() { return offset+length; }
+
+ @Override
+ public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index < 0) {
+ insertIndex(end(), key, value);
+ length++;
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE oldValue = values[index];
+ values[index] = value;
+ return oldValue;
+ }
+
+ @Override
+ public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ insertIndex(end(), key, value);
+ length++;
+ }
+ return getDefaultReturnValue();
+ }
+
+#if VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index < 0) {
+ insertIndex(end(), key, value);
+ length++;
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE oldValue = values[index];
+ values[index] += value;
+ return oldValue;
+ }
+
+#endif
+ @Override
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index < 0) {
+ insertIndex(offset, key, value);
+ length++;
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE lastValue = values[index];
+ values[index] = value;
+ moveIndexToFirst(index);
+ return lastValue;
+ }
+
+ @Override
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key);
+ if(index < 0) {
+ insertIndex(end(), key, value);
+ length++;
+ return getDefaultReturnValue();
+ }
+ VALUE_TYPE lastValue = values[index];
+ values[index] = value;
+ moveIndexToLast(index);
+ return lastValue;
+ }
+
+ @Override
+ public boolean moveToFirst(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ moveIndexToFirst(index);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean moveToLast(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ moveIndexToLast(index);
+ return true;
+ }
+ return false;
+ }
+
+#if !TYPE_OBJECT
+ @Override
+ public boolean containsKey(KEY_TYPE key) {
+ return findIndex(key) >= 0;
+ }
+
+#endif
+#if !VALUE_OBJECT
+ @Override
+ public boolean containsValue(VALUE_TYPE value) {
+ return findValue(value) >= 0;
+ }
+
+#endif
+ @Override
+ public boolean containsKey(Object key) {
+ return findIndex(key) >= 0;
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return findValue(value) >= 0;
+ }
+
+ @Override
+ public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
+ int index = findIndex(key);
+ return index < 0 ? getDefaultReturnValue() : values[index];
+ }
+
+#if !TYPE_OBJECT
+ @Override
+ public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
+ int index = findIndex(key);
+ return index < 0 ? defaultValue : values[index];
+ }
+
+#endif
+ @Override
+ public CLASS_VALUE_TYPE get(Object key) {
+ int index = findIndex(key);
+ return VALUE_TO_OBJ(index < 0 ? getDefaultReturnValue() : values[index]);
+ }
+
+ @Override
+ public CLASS_VALUE_TYPE getOrDefault(Object key, CLASS_VALUE_TYPE defaultValue) {
+ int index = findIndex(key);
+ return index < 0 ? defaultValue : VALUE_TO_OBJ(values[index]);
+ }
+
+ @Override
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ VALUE_TYPE value = values[index];
+ moveIndexToFirst(index);
+ return value;
+ }
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index >= 0) {
+ VALUE_TYPE value = values[index];
+ moveIndexToLast(index);
+ return value;
+ }
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public KEY_TYPE FIRST_ENTRY_KEY() {
+ if(length <= 0) throw new NoSuchElementException();
+ return keys[offset];
+ }
+
+ @Override
+ public KEY_TYPE LAST_ENTRY_KEY() {
+ if(length <= 0) throw new NoSuchElementException();
+ return keys[end()-1];
+ }
+
+ @Override
+ public VALUE_TYPE FIRST_ENTRY_VALUE() {
+ if(length <= 0) throw new NoSuchElementException();
+ return values[end()-1];
+ }
+
+ @Override
+ public VALUE_TYPE LAST_ENTRY_VALUE() {
+ if(length <= 0) throw new NoSuchElementException();
+ return values[offset];
+ }
+
+ @Override
+ public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
+ if(length == 0) throw new NoSuchElementException();
+ KEY_TYPE result = keys[offset];
+ removeIndex(offset);
+ length--;
+ return result;
+ }
+
+ @Override
+ public KEY_TYPE POLL_LAST_ENTRY_KEY() {
+ if(length == 0) throw new NoSuchElementException();
+ KEY_TYPE result = keys[end()-1];
+ removeIndex(end()-1);
+ length--;
+ return result;
+ }
+
+ @Override
+ public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
+ int index = findIndex(key);
+ if(index < 0) return getDefaultReturnValue();
+ VALUE_TYPE value = values[index];
+ removeIndex(index);
+ return value;
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ @Override
+ public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
+ int index = findIndex(key, value);
+ if(index < 0) return false;
+ removeIndex(index);
+ return true;
+ }
+
+#endif
+ @Override
+ public CLASS_VALUE_TYPE remove(Object key) {
+ int index = findIndex(key);
+ if(index < 0) return VALUE_TO_OBJ(getDefaultReturnValue());
+ VALUE_TYPE value = values[index];
+ removeIndex(index);
+ return VALUE_TO_OBJ(value);
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ int index = findIndex(key, value);
+ if(index < 0) return false;
+ removeIndex(index);
+ return true;
+ }
+
+ @Override
+ public int size() {
+ return length;
+ }
+
+ @Override
+ public void clear() {
+ removeRange(offset, offset+length);
+ length = 0;
+ }
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet() {
+ if(keySet == null) keySet = new SubKeySet();
+ return keySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(valuesC == null) valuesC = new SubValues();
+ return valuesC;
+ }
+
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new SubMapEntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() {
+ return null;
+ }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey) {
+ int fromIndex = findIndex(fromKey);
+ int toIndex = findIndex(toKey);
+ if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException();
+ return new SubMap(fromIndex, toIndex - fromIndex + 1);
+ }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey) {
+ int toIndex = findIndex(toKey);
+ if(toIndex == -1) throw new NoSuchElementException();
+ return new SubMap(offset, toIndex + 1);
+ }
+
+ @Override
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey) {
+ int fromIndex = findIndex(fromKey);
+ if(fromIndex == -1) throw new NoSuchElementException();
+ return new SubMap(fromIndex, size - fromIndex);
+ }
+
+ protected void moveIndexToFirst(int index) {
+ if(index == 0) return;
+ KEY_TYPE key = keys[index];
+ VALUE_TYPE value = values[index];
+ System.arraycopy(keys, offset, keys, offset+1, index);
+ System.arraycopy(values, offset, values, offset+1, index);
+ keys[offset] = key;
+ values[offset] = value;
+ }
+
+ protected void moveIndexToLast(int index) {
+ if(index == length-1) return;
+ KEY_TYPE key = keys[index];
+ VALUE_TYPE value = values[index];
+ System.arraycopy(keys, offset+index+1, keys, offset+index, length-index-1);
+ System.arraycopy(values, offset+index+1, values, offset+index, length-index-1);
+ keys[end()-1] = key;
+ values[end()-1] = value;
+ }
+
+#if !TYPE_OBJECT || !VALUE_OBJECT
+ protected int findIndex(KEY_TYPE key, VALUE_TYPE value) {
+ for(int i = length-1;i>=0;i--)
+ if(KEY_EQUALS(keys[offset+i], key) && VALUE_EQUALS(values[offset+i], value)) return i;
+ return -1;
+ }
+
+#endif
+#if !TYPE_OBJECT
+ protected int findIndex(KEY_TYPE key) {
+ for(int i = length-1;i>=0;i--)
+ if(KEY_EQUALS(keys[offset+i], key)) return i;
+ return -1;
+ }
+
+#endif
+#if !VALUE_OBJECT
+ protected int findValue(VALUE_TYPE value) {
+ for(int i = length-1;i>=0;i--)
+ if(VALUE_EQUALS(values[offset+i], value)) return i;
+ return -1;
+ }
+
+#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;
+ 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;
+ 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;
+ return -1;
+ }
+
+ private class SubMapEntrySet extends AbstractObjectSet implements SORTED_MAP.FastSortedSet KEY_VALUE_GENERIC_TYPE {
+ @Override
+ public boolean addAndMoveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public boolean moveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
+ return SubMap.this.moveToFirst(o.ENTRY_KEY());
+ }
+
+ @Override
+ public boolean moveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
+ return SubMap.this.moveToLast(o.ENTRY_KEY());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE first() {
+ return new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE last() {
+ return new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirst() {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
+ POLL_FIRST_ENTRY_KEY();
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLast() {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
+ POLL_LAST_ENTRY_KEY();
+ return entry;
+ }
+
+ @Override
+ public ObjectBidirectionalIterator iterator() {
+ return new SubEntryIterator();
+ }
+
+ @Override
+ public ObjectBidirectionalIterator iterator(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) {
+ return new SubEntryIterator(fromElement.ENTRY_KEY());
+ }
+
+ @Override
+ public ObjectBidirectionalIterator fastIterator() {
+ return new SubFastEntryIterator();
+ }
+
+ @Override
+ public ObjectBidirectionalIterator fastIterator(KEY_TYPE fromElement) {
+ return new SubFastEntryIterator(fromElement);
+ }
+
+ @Override
+ public void forEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ for(int i = 0;i action) {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
+ for(int i = 0;i)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return SubMap.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return SubMap.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return SubMap.this.size();
+ }
+
+ @Override
+ public void clear() {
+ SubMap.this.clear();
+ }
+
+ @Override
+ public Comparator comparator() {
+ return null;
+ }
+ @Override
+ public ObjectSortedSet subSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement, MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
+ @Override
+ public ObjectSortedSet headSet(MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
+ @Override
+ public ObjectSortedSet tailSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) { throw new UnsupportedOperationException(); }
+ }
+
+ private class SubKeySet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
+#if TYPE_OBJECT
+ @Override
+ public boolean contains(Object e) { return containsKey(e); }
+
+ @Override
+ public boolean remove(Object o) {
+ int oldSize = length;
+ remove(o);
+ return length != oldSize;
+ }
+
+#else
+ @Override
+ public boolean contains(KEY_TYPE e) { return containsKey(e); }
+
+ @Override
+ public boolean remove(KEY_TYPE o) {
+ int oldSize = length;
+ remove(o);
+ return length != oldSize;
+ }
+
+#endif
+ @Override
+ public boolean add(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToFirst(KEY_TYPE o) { return SubMap.this.moveToFirst(o); }
+ @Override
+ public boolean moveToLast(KEY_TYPE o) { return SubMap.this.moveToLast(o); }
+ @Override
+ public LIST_ITERATOR KEY_GENERIC_TYPE iterator() { return new SubKeyIterator(); }
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) { return new SubKeyIterator(fromElement); }
+ @Override
+ public int size() { return SubMap.this.size(); }
+ @Override
+ public void clear() { SubMap.this.clear(); }
+ @Override
+ public KEY_TYPE FIRST_KEY() { return FIRST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE POLL_FIRST_KEY() { return POLL_FIRST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE LAST_KEY() { return LAST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE POLL_LAST_KEY() { return POLL_LAST_ENTRY_KEY(); }
+
+#if TYPE_OBJECT
+ @Override
+ public void forEach(Consumer super CLASS_TYPE> action) {
+ for(int i = 0;i action) {
+ for(int i = 0;i {
+ MapEntry entry = new MapEntry();
+
+ public SubFastEntryIterator() {}
+ public SubFastEntryIterator(KEY_TYPE from) {
+ index = findIndex(from);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ entry.index = nextEntry();
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ entry.index = previousEntry();
+ return entry;
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class SubEntryIterator extends SubMapIterator implements ObjectListIterator {
+ MapEntry entry = null;
+
+ public SubEntryIterator() {}
+ public SubEntryIterator(KEY_TYPE from) {
+ index = findIndex(from);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ return entry = new MapEntry(nextEntry());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ return entry = new MapEntry(previousEntry());
+ }
+
+ @Override
+ public void remove() {
+ super.remove();
+ entry.index = -1;
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class SubKeyIterator extends SubMapIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
+ public SubKeyIterator() {}
+ public SubKeyIterator(KEY_TYPE element) {
+ index = findIndex(element);
+ }
+ @Override
+ public KEY_TYPE PREVIOUS() {
+ return keys[previousEntry()];
+ }
+
+ @Override
+ public KEY_TYPE NEXT() {
+ return keys[nextEntry()];
+ }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class SubValueIterator extends SubMapIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
+ @Override
+ public VALUE_TYPE VALUE_PREVIOUS() {
+ return values[previousEntry()];
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return values[nextEntry()];
+ }
+
+ @Override
+ public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class SubMapIterator {
+ int index;
+ int lastReturned = -1;
+
+ public boolean hasNext() {
+ return index < length;
+ }
+
+ public boolean hasPrevious() {
+ return index > 0;
+ }
+
+ public int nextIndex() {
+ return index;
+ }
+
+ public int previousIndex() {
+ return index-1;
+ }
+
+ public void remove() {
+ if(lastReturned == -1)
+ throw new IllegalStateException();
+ removeIndex(lastReturned);
+ if(lastReturned < index)
+ index--;
+ lastReturned = -1;
+ }
+
+ public int previousEntry() {
+ int returnIndex = offset+index;
+ lastReturned = index--;
+ return returnIndex;
+ }
+
+ public int nextEntry() {
+ int returnIndex = offset+index;
+ lastReturned = index++;
+ return returnIndex;
+ }
+
+ 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;
+ }
+
+ 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 MapEntrySet extends AbstractObjectSet implements SORTED_MAP.FastSortedSet KEY_VALUE_GENERIC_TYPE {
+ @Override
+ public boolean addAndMoveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public boolean moveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
+ return ARRAY_MAP.this.moveToFirst(o.ENTRY_KEY());
+ }
+
+ @Override
+ public boolean moveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
+ return ARRAY_MAP.this.moveToLast(o.ENTRY_KEY());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE first() {
+ return new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE last() {
+ return new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirst() {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
+ POLL_FIRST_ENTRY_KEY();
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLast() {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
+ POLL_LAST_ENTRY_KEY();
+ return entry;
+ }
+
+ @Override
+ public ObjectBidirectionalIterator iterator() {
+ return new EntryIterator();
+ }
+
+ @Override
+ public ObjectBidirectionalIterator iterator(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) {
+ return new EntryIterator(fromElement.ENTRY_KEY());
+ }
+
+ @Override
+ public ObjectBidirectionalIterator fastIterator() {
+ return new FastEntryIterator();
+ }
+
+ @Override
+ public ObjectBidirectionalIterator fastIterator(KEY_TYPE fromElement) {
+ return new FastEntryIterator(fromElement);
+ }
+
+ @Override
+ public void forEach(Consumer super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
+ for(int i = 0;i action) {
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
+ for(int i = 0;i)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return ARRAY_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return ARRAY_MAP.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return ARRAY_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ ARRAY_MAP.this.clear();
+ }
+
+ @Override
+ public Comparator comparator() {
+ return null;
+ }
+ @Override
+ public ObjectSortedSet subSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement, MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
+ @Override
+ public ObjectSortedSet headSet(MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
+ @Override
+ public ObjectSortedSet tailSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) { throw new UnsupportedOperationException(); }
+ }
+
+ private class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
+#if TYPE_OBJECT
+ @Override
+ public boolean contains(Object e) { return containsKey(e); }
+
+ @Override
+ public boolean remove(Object o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#else
+ @Override
+ public boolean contains(KEY_TYPE e) { return containsKey(e); }
+
+ @Override
+ public boolean remove(KEY_TYPE o) {
+ int oldSize = size;
+ remove(o);
+ return size != oldSize;
+ }
+
+#endif
+ @Override
+ public boolean add(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToFirst(KEY_TYPE o) { return ARRAY_MAP.this.moveToFirst(o); }
+ @Override
+ public boolean moveToLast(KEY_TYPE o) { return ARRAY_MAP.this.moveToLast(o); }
+ @Override
+ public LIST_ITERATOR KEY_GENERIC_TYPE iterator() { return new KeyIterator(); }
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) { return new KeyIterator(fromElement); }
+ @Override
+ public int size() { return ARRAY_MAP.this.size(); }
+ @Override
+ public void clear() { ARRAY_MAP.this.clear(); }
+ @Override
+ public KEY_TYPE FIRST_KEY() { return FIRST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE POLL_FIRST_KEY() { return POLL_FIRST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE LAST_KEY() { return LAST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE POLL_LAST_KEY() { return POLL_LAST_ENTRY_KEY(); }
+
+#if TYPE_OBJECT
+ @Override
+ public void forEach(Consumer super CLASS_TYPE> action) {
+ for(int i = 0;i action) {
+ for(int i = 0;i {
+ MapEntry entry = new MapEntry();
+
+ public FastEntryIterator() {}
+ public FastEntryIterator(KEY_TYPE from) {
+ index = findIndex(from);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ entry.index = nextEntry();
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ entry.index = previousEntry();
+ return entry;
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class EntryIterator extends MapIterator implements ObjectListIterator {
+ MapEntry entry = null;
+
+ public EntryIterator() {}
+ public EntryIterator(KEY_TYPE from) {
+ index = findIndex(from);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ return entry = new MapEntry(nextEntry());
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ return entry = new MapEntry(previousEntry());
+ }
+
+ @Override
+ public void remove() {
+ super.remove();
+ entry.index = -1;
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class KeyIterator extends MapIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
+ public KeyIterator() {}
+ public KeyIterator(KEY_TYPE element) {
+ index = findIndex(element);
+ }
+ @Override
+ public KEY_TYPE PREVIOUS() {
+ return keys[previousEntry()];
+ }
+
+ @Override
+ public KEY_TYPE NEXT() {
+ return keys[nextEntry()];
+ }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class ValueIterator extends MapIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
+ @Override
+ public VALUE_TYPE VALUE_PREVIOUS() {
+ return values[previousEntry()];
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return values[nextEntry()];
+ }
+
+ @Override
+ public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ private class MapIterator {
+ int index;
+ int lastReturned = -1;
+
+ public boolean hasNext() {
+ return index < size;
+ }
+
+ public boolean hasPrevious() {
+ return index > 0;
+ }
+
+ public int nextIndex() {
+ return index;
+ }
+
+ public int previousIndex() {
+ return index-1;
+ }
+
+ public void remove() {
+ if(lastReturned == -1)
+ throw new IllegalStateException();
+ removeIndex(lastReturned);
+ if(lastReturned < index)
+ index--;
+ lastReturned = -1;
+ }
+
+ public int previousEntry() {
+ lastReturned = index;
+ return index--;
+ }
+
+ public int nextEntry() {
+ lastReturned = index;
+ return index++;
+ }
+
+ 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;
+ }
+
+ 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 MapEntry implements MAP.Entry KEY_VALUE_GENERIC_TYPE, Map.Entry {
+ 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]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/impl/misc/EnumMap.template b/src/main/resources/speiger/assets/collections/templates/maps/impl/misc/EnumMap.template
new file mode 100644
index 0000000..6c078c8
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/impl/misc/EnumMap.template
@@ -0,0 +1,332 @@
+package speiger.src.collections.PACKAGE.maps.impl.misc;
+
+import java.util.Map;
+import java.util.NoSuchElementException;
+#if VALUE_OBJECT
+import java.util.Objects;
+#endif
+
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
+#if !VALUE_OBJECT
+import speiger.src.collections.objects.collections.ObjectIterator;
+#endif
+import speiger.src.collections.objects.maps.abstracts.ABSTRACT_MAP;
+import speiger.src.collections.objects.maps.interfaces.MAP;
+import speiger.src.collections.objects.sets.AbstractObjectSet;
+import speiger.src.collections.objects.sets.ObjectSet;
+import sun.misc.SharedSecrets;
+
+public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE
+{
+ protected final Class keyType;
+ protected transient final T[] keys;
+ protected transient final VALUE_TYPE[] values;
+ protected transient final long[] present;
+ protected int size = 0;
+ protected transient ObjectSet entrySet;
+ protected transient ObjectSet keySet;
+ protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC;
+
+ public ENUM_MAP(Class keyType) {
+ this.keyType = keyType;
+ keys = getKeyUniverse(keyType);
+ values = NEW_VALUE_ARRAY(keys.length);
+ present = new long[((keys.length - 1) >> 6) + 1];
+ }
+
+ @Override
+ public VALUE_TYPE put(T key, VALUE_TYPE value) {
+ int index = key.ordinal();
+ if(isSet(index)) {
+ VALUE_TYPE result = values[index];
+ values[index] = value;
+ return result;
+ }
+ set(index);
+ values[index] = value;
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE putIfAbsent(T key, VALUE_TYPE value) {
+ int index = key.ordinal();
+ if(isSet(index)) return values[index];
+ set(index);
+ values[index] = value;
+ return getDefaultReturnValue();
+ }
+
+#if VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(T key, VALUE_TYPE value) {
+ int index = key.ordinal();
+ if(isSet(index)) {
+ VALUE_TYPE result = values[index];
+ values[index] += value;
+ return result;
+ }
+ set(index);
+ values[index] = value;
+ return getDefaultReturnValue();
+ }
+
+#endif
+ @Override
+ public boolean containsKey(Object key) {
+ return isSet(((T)key).ordinal());
+ }
+
+#if VALUE_OBJECT
+ @Override
+ public boolean containsValue(Object value) {
+ for(int i = 0;i ENTRY_SET() {
+ if(entrySet == null) entrySet = new EntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public ObjectSet keySet() {
+ if(keySet == null) keySet = new KeySet();
+ return keySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(valuesC == null) valuesC = new Values();
+ return valuesC;
+ }
+
+ protected void onNodeAdded(int index) {
+
+ }
+
+ protected void onNodeRemoved(int index) {
+
+ }
+
+ protected void set(int index) {
+ present[index >> 6] |= (1L << index);
+ onNodeAdded(index);
+ }
+ protected void clear(int index) {
+ present[index >> 6] &= ~(1L << index);
+ onNodeRemoved(index);
+ }
+ protected boolean isSet(int index) { return (present[index >> 6] & (1L << index)) != 0; }
+ private static > K[] getKeyUniverse(Class keyType) { return SharedSecrets.getJavaLangAccess().getEnumConstantsShared(keyType); }
+
+ class EntrySet extends AbstractObjectSet {
+
+ @Override
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) return containsKey(((Map.Entry, ?>)o).getKey());
+ return false;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return ENUM_MAP.this.remove(entry.getKey(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (java.util.Map.Entry, ?>)o;
+ return ENUM_MAP.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+
+ @Override
+ public ObjectIterator iterator() {
+ return new EntryIterator();
+ }
+
+ @Override
+ public int size() {
+ return ENUM_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ ENUM_MAP.this.clear();
+ }
+ }
+
+ class KeySet extends AbstractObjectSet {
+
+ @Override
+ public boolean contains(Object o) {
+ return containsKey(o);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ int size = size();
+ ENUM_MAP.this.remove(o);
+ return size != size();
+ }
+
+ @Override
+ public ObjectIterator iterator() {
+ return new KeyIterator();
+ }
+
+ @Override
+ public int size() {
+ return ENUM_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ ENUM_MAP.this.clear();
+ }
+ }
+
+ class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+
+ @Override
+ public boolean add(VALUE_TYPE o) { throw new UnsupportedOperationException(); }
+
+#if TYPE_OBJECT
+ @Override
+ public boolean contains(Object e) { return containsValue(e); }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) { return containsValue(e); }
+
+#endif
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
+ return new ValueIterator();
+ }
+
+ @Override
+ public int size() {
+ return ENUM_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ ENUM_MAP.this.clear();
+ }
+ }
+
+ class EntryIterator extends MapIterator implements ObjectIterator {
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ int index = nextEntry();
+ return new BasicEntry<>(keys[index], values[index]);
+ }
+ }
+
+ class KeyIterator extends MapIterator implements ObjectIterator {
+ @Override
+ public T next() {
+ return keys[nextEntry()];
+ }
+ }
+
+ class ValueIterator extends MapIterator implements VALUE_ITERATOR VALUE_GENERIC_TYPE {
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return values[nextEntry()];
+ }
+ }
+
+ class MapIterator {
+ int index;
+ int lastReturnValue = -1;
+ int nextIndex = -1;
+
+ public boolean hasNext() {
+ if(nextIndex == -1 && index < values.length) {
+ while(index < values.length && !isSet(index++));
+ nextIndex = index-1;
+ if(!isSet(nextIndex)) nextIndex = -1;
+ }
+ return nextIndex != -1;
+ }
+
+ public int nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ lastReturnValue = nextIndex;
+ return nextIndex;
+ }
+
+ public void remove() {
+ if(lastReturnValue == -1) throw new IllegalStateException();
+ clear(lastReturnValue);
+ values[lastReturnValue] = EMPTY_VALUE;
+ }
+ }
+}
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/impl/tree/AVLTreeMap.template b/src/main/resources/speiger/assets/collections/templates/maps/impl/tree/AVLTreeMap.template
new file mode 100644
index 0000000..20c9f48
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/impl/tree/AVLTreeMap.template
@@ -0,0 +1,1688 @@
+package speiger.src.collections.PACKAGE.maps.impl.tree;
+
+import java.util.Map;
+#if TYPE_OBJECT
+import java.util.Comparator;
+import java.util.Objects;
+#endif
+import java.util.NoSuchElementException;
+
+import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.functions.COMPARATOR;
+#endif
+import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
+import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.NAVIGABLE_MAP;
+import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
+import speiger.src.collections.PACKAGE.sets.NAVIGABLE_SET;
+import speiger.src.collections.PACKAGE.sets.SET;
+import speiger.src.collections.PACKAGE.sets.SORTED_SET;
+import speiger.src.collections.PACKAGE.utils.ITERATORS;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
+#if !SAME_TYPE
+import speiger.src.collections.VALUE_PACKAGE.lists.VALUE_LIST_ITERATOR;
+import speiger.src.collections.VALUE_PACKAGE.utils.VALUE_ITERATORS;
+#endif
+#if !TYPE_OBJECT && !VALUE_OBJECT
+import speiger.src.collections.objects.lists.ObjectListIterator;
+import speiger.src.collections.objects.utils.ObjectIterators;
+#endif
+#if !VALUE_OBJECT
+import speiger.src.collections.objects.collections.ObjectIterator;
+#endif
+#if !TYPE_OBJECT
+import speiger.src.collections.objects.sets.AbstractObjectSet;
+import speiger.src.collections.objects.sets.ObjectSet;
+#endif
+
+public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE
+{
+ protected transient Entry KEY_VALUE_GENERIC_TYPE tree;
+ protected transient Entry KEY_VALUE_GENERIC_TYPE first;
+ protected transient Entry KEY_VALUE_GENERIC_TYPE last;
+ protected int size = 0;
+ protected transient COMPARATOR KEY_GENERIC_TYPE comparator;
+
+#if TYPE_OBJECT
+ protected KEY_TYPE defaultMaxNotFound = null;
+ protected KEY_TYPE defaultMinNotFound = null;
+#else
+ protected KEY_TYPE defaultMaxNotFound = CLASS_TYPE.MIN_VALUE;
+ protected KEY_TYPE defaultMinNotFound = CLASS_TYPE.MAX_VALUE;
+#endif
+
+ protected NAVIGABLE_SET KEY_GENERIC_TYPE keySet;
+ protected VALUE_COLLECTION VALUE_GENERIC_TYPE values;
+ protected ObjectSet entrySet;
+#if TYPE_OBJECT
+ public KEY_TYPE getDefaultMaxValue() { return defaultMaxNotFound; }
+ public KEY_TYPE getDefaultMinValue() { return defaultMinNotFound; }
+
+#else
+ @Override
+ public void setDefaultMaxValue(KEY_TYPE value) { defaultMaxNotFound = value; }
+ @Override
+ public KEY_TYPE getDefaultMaxValue() { return defaultMaxNotFound; }
+ @Override
+ public void setDefaultMinValue(KEY_TYPE value) { defaultMinNotFound = value; }
+ @Override
+ public KEY_TYPE getDefaultMinValue() { return defaultMinNotFound; }
+
+#endif
+ @Override
+ public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
+ if(tree == null) {
+ tree = first = last = new EntryKV_BRACES(key, value, null);
+ size++;
+ return getDefaultReturnValue();
+ }
+ int compare = 0;
+ Entry KEY_VALUE_GENERIC_TYPE parent = tree;
+ while(true) {
+ if((compare = compare(key, parent.key)) == 0) return parent.setValue(value);
+ if(compare < 0) {
+ if(parent.left == null) break;
+ parent = parent.left;
+ }
+ else if(compare > 0) {
+ if(parent.right == null) break;
+ parent = parent.right;
+ }
+ }
+ Entry KEY_VALUE_GENERIC_TYPE adding = new EntryKV_BRACES(key, value, parent);
+ if(compare < 0) {
+ parent.left = adding;
+ if(parent == first) first = adding;
+ }
+ else {
+ parent.right = adding;
+ if(parent == last) last = adding;
+ }
+ fixAfterInsertion(adding);
+ size++;
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
+ if(tree == null) {
+ tree = first = last = new EntryKV_BRACES(key, value, null);
+ size++;
+ return getDefaultReturnValue();
+ }
+ int compare = 0;
+ Entry KEY_VALUE_GENERIC_TYPE parent = tree;
+ while(true) {
+ if((compare = compare(key, parent.key)) == 0) return parent.value;
+ if(compare < 0) {
+ if(parent.left == null) break;
+ parent = parent.left;
+ }
+ else if(compare > 0) {
+ if(parent.right == null) break;
+ parent = parent.right;
+ }
+ }
+ Entry KEY_VALUE_GENERIC_TYPE adding = new EntryKV_BRACES(key, value, parent);
+ if(compare < 0) {
+ parent.left = adding;
+ if(parent == first) first = adding;
+ }
+ else {
+ parent.right = adding;
+ if(parent == last) last = adding;
+ }
+ fixAfterInsertion(adding);
+ size++;
+ return getDefaultReturnValue();
+ }
+
+#if VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
+ if(tree == null) {
+ tree = first = last = new EntryKV_BRACES(key, value, null);
+ size++;
+ return getDefaultReturnValue();
+ }
+ int compare = 0;
+ Entry KEY_VALUE_GENERIC_TYPE parent = tree;
+ while(true) {
+ if((compare = compare(key, parent.key)) == 0) return parent.addTo(value);
+ if(compare < 0) {
+ if(parent.left == null) break;
+ parent = parent.left;
+ }
+ else if(compare > 0) {
+ if(parent.right == null) break;
+ parent = parent.right;
+ }
+ }
+ Entry KEY_VALUE_GENERIC_TYPE adding = new EntryKV_BRACES(key, value, parent);
+ if(compare < 0) {
+ parent.left = adding;
+ if(parent == first) first = adding;
+ }
+ else {
+ parent.right = adding;
+ if(parent == last) last = adding;
+ }
+ fixAfterInsertion(adding);
+ size++;
+ return getDefaultReturnValue();
+ }
+
+#endif
+ @Override
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToFirst(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToLast(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; }
+
+#if TYPE_OBJECT
+ @Override
+ public boolean containsKey(Object key) {
+ return findNode((KEY_TYPE)key) != null;
+ }
+
+#else
+ @Override
+ public boolean containsKey(KEY_TYPE key) {
+ return findNode(key) != null;
+ }
+
+#endif
+
+ @Override
+ public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findNode(key);
+ return node == null ? getDefaultReturnValue() : node.value;
+ }
+
+#if TYPE_OBJECT
+ @Override
+ public VALUE_TYPE getOrDefault(Object key, VALUE_TYPE defaultValue) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findNode((CLASS_TYPE)key);
+ return node == null ? defaultValue : node.value;
+ }
+
+#else
+ @Override
+ public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findNode(key);
+ return node == null ? defaultValue : node.value;
+ }
+
+#endif
+ @Override
+ public KEY_TYPE FIRST_ENTRY_KEY() {
+ if(tree == null) throw new NoSuchElementException();
+ return first.key;
+ }
+
+ @Override
+ public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
+ if(tree == null) throw new NoSuchElementException();
+ KEY_TYPE result = first.key;
+ removeNode(first);
+ return result;
+ }
+
+ @Override
+ public KEY_TYPE LAST_ENTRY_KEY() {
+ if(tree == null) throw new NoSuchElementException();
+ return last.key;
+ }
+
+ @Override
+ public KEY_TYPE POLL_LAST_ENTRY_KEY() {
+ if(tree == null) throw new NoSuchElementException();
+ KEY_TYPE result = last.key;
+ removeNode(last);
+ return result;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE firstEntry() {
+ if(tree == null) throw new NoSuchElementException();
+ return new BasicEntryKV_BRACES(first.key, first.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lastEntry() {
+ if(tree == null) throw new NoSuchElementException();
+ return new BasicEntryKV_BRACES(last.key, last.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirstEntry() {
+ if(tree == null) throw new NoSuchElementException();
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(first.key, first.value);
+ removeNode(first);
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLastEntry() {
+ if(tree == null) throw new NoSuchElementException();
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(last.key, last.value);
+ removeNode(last);
+ return entry;
+ }
+
+ @Override
+ public VALUE_TYPE FIRST_ENTRY_VALUE() {
+ if(tree == null) throw new NoSuchElementException();
+ return first.value;
+ }
+
+ @Override
+ public VALUE_TYPE LAST_ENTRY_VALUE() {
+ if(tree == null) throw new NoSuchElementException();
+ return last.value;
+ }
+
+ @Override
+ public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
+ if(entry == null) return getDefaultReturnValue();
+ VALUE_TYPE value = entry.value;
+ removeNode(entry);
+ return value;
+ }
+
+#if TYPE_OBJECT && VALUE_OBJECT
+ @Override
+ public boolean remove(Object key, Object value) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = findNode((CLASS_TYPE)key);
+ if(entry == null || !Objects.equals(value, entry.value)) return false;
+ removeNode(entry);
+ return true;
+ }
+
+#else
+ @Override
+ public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
+ if(entry == null || entry.value != value) return false;
+ removeNode(entry);
+ return true;
+ }
+
+#endif
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(boolean descending) {
+ LIST_ITERATOR KEY_GENERIC_TYPE iter = new KeyIterator(descending);
+ return descending ? ITERATORS.invert(iter) : iter;
+ }
+
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(KEY_TYPE key) {
+ return new KeyIterator(findNode(key));
+ }
+
+ @Override
+ public SORTED_SET KEY_GENERIC_TYPE keySet() {
+ return navigableKeySet();
+ }
+
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new EntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(values == null) values = new Values();
+ return values;
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE navigableKeySet() {
+ if(keySet == null) keySet = new KeySetKV_BRACES(this);
+ return keySet;
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap() {
+ return new DescendingSubMapKV_BRACES(this, true, EMPTY_KEY_VALUE, true, true, EMPTY_KEY_VALUE, true);
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE descendingKeySet() {
+ return descendingMap().navigableKeySet();
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive) {
+ return new AscendingSubMapKV_BRACES(this, false, fromKey, fromInclusive, false, toKey, toInclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive) {
+ return new AscendingSubMapKV_BRACES(this, true, EMPTY_KEY_VALUE, true, false, toKey, inclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive) {
+ return new AscendingSubMapKV_BRACES(this, false, fromKey, inclusive, true, EMPTY_KEY_VALUE, true);
+ }
+
+ @Override
+ public KEY_TYPE lowerKey(KEY_TYPE e) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findLowerNode(e);
+ return node != null ? node.key : defaultMinNotFound;
+ }
+
+ @Override
+ public KEY_TYPE floorKey(KEY_TYPE e) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findFloorNode(e);
+ return node != null ? node.key : defaultMinNotFound;
+ }
+
+ @Override
+ public KEY_TYPE higherKey(KEY_TYPE e) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findHigherNode(e);
+ return node != null ? node.key : defaultMaxNotFound;
+ }
+
+ @Override
+ public KEY_TYPE ceilingKey(KEY_TYPE e) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findCeilingNode(e);
+ return node != null ? node.key : defaultMaxNotFound;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findLowerNode(key);
+ return node != null ? new BasicEntryKV_BRACES(node.key, node.value) : null;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findHigherNode(key);
+ return node != null ? new BasicEntryKV_BRACES(node.key, node.value) : null;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findFloorNode(key);
+ return node != null ? new BasicEntryKV_BRACES(node.key, node.value) : null;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findCeilingNode(key);
+ return node != null ? new BasicEntryKV_BRACES(node.key, node.value) : null;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findLowerNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = tree;
+ while(entry != null) {
+ if(compare(key, entry.key) > 0) {
+ if(entry.right != null) entry = entry.right;
+ else return entry;
+ }
+ else {
+ if(entry.left != null) entry = entry.left;
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ while(parent != null && parent.left == entry) {
+ entry = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ }
+ }
+ return null;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findFloorNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = tree;
+ int compare;
+ while(entry != null) {
+ if((compare = compare(key, entry.key)) > 0) {
+ if(entry.right == null) break;
+ entry = entry.right;
+ continue;
+ }
+ else if(compare < 0) {
+ if(entry.left != null) entry = entry.left;
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ while(parent != null && parent.left == entry) {
+ entry = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ continue;
+ }
+ break;
+ }
+ return entry;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findCeilingNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = tree;
+ int compare;
+ while(entry != null) {
+ if((compare = compare(key, entry.key)) < 0) {
+ if(entry.left == null) break;
+ entry = entry.left;
+ continue;
+ }
+ else if(compare > 0) {
+ if(entry.right != null) entry = entry.right;
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ while(parent != null && parent.right == entry) {
+ entry = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ continue;
+ }
+ break;
+ }
+ return entry;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findHigherNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = tree;
+ while(entry != null) {
+ if(compare(key, entry.key) < 0) {
+ if(entry.left != null) entry = entry.left;
+ else return entry;
+ }
+ else {
+ if(entry.right != null) entry = entry.right;
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ while(parent != null && parent.right == entry) {
+ entry = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ }
+ }
+ return null;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = tree;
+ int compare;
+ while(node != null) {
+ if((compare = compare(key, node.key)) == 0) return node;
+ if(compare < 0) node = node.left;
+ else node = node.right;
+ }
+ return null;
+ }
+
+ protected void removeNode(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ size--;
+ if(entry.needsSuccessor()) {
+ Entry KEY_VALUE_GENERIC_TYPE successor = entry.next();
+ entry.key = successor.key;
+ entry.value = successor.value;
+ entry = successor;
+ }
+ Entry KEY_VALUE_GENERIC_TYPE replacement = entry.left != null ? entry.left : entry.right;
+ if(replacement != null) {
+ if(entry.replace(replacement)) tree = replacement;
+ if(entry == first) first = replacement;
+ if(entry == last) last = entry.right != null ? entry.right : replacement;
+ entry.left = entry.right = entry.parent = null;
+ fixAfterDeletion(replacement);
+ }
+ else if(entry.parent == null) tree = first = last = null;
+ else {
+ fixAfterDeletion(entry);
+ entry.replace(null);
+ if(entry.parent != null) {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ if(entry == first) first = parent.left != null ? parent.left : parent;
+ if(entry == last) last = entry.right != null ? parent.right : parent;
+ }
+ entry.parent = null;
+ }
+ }
+
+ protected int compare(KEY_TYPE k, KEY_TYPE v) { return comparator != null ? comparator.compare(k, v) : COMPAREABLE_TO_KEY(k, v);}
+
+ /** From CLR */
+ protected void rotateLeft(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ if(entry != null) {
+ Entry KEY_VALUE_GENERIC_TYPE right = entry.right;
+ entry.right = right.left;
+ if(right.left != null) right.left.parent = entry;
+ right.parent = entry.parent;
+ if(entry.parent == null) tree = right;
+ else if(entry.parent.left == entry) entry.parent.left = right;
+ else entry.parent.right = right;
+ right.left = entry;
+ entry.parent = right;
+ }
+ }
+
+ /** From CLR */
+ protected void rotateRight(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ if(entry != null) {
+ Entry KEY_VALUE_GENERIC_TYPE left = entry.left;
+ entry.left = left.right;
+ if(left.right != null) left.right.parent = entry;
+ left.parent = entry.parent;
+ if(entry.parent == null) tree = left;
+ else if(entry.parent.right == entry) entry.parent.right = left;
+ else entry.parent.left = left;
+ left.right = entry;
+ entry.parent = left;
+ }
+ }
+
+ /** From CLR */
+ protected void fixAfterInsertion(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ while(entry != null) {
+ entry.updateHeight();
+ int balance = entry.getBalance();
+ if(balance > 1) {
+ int compare = entry.left.getBalance();
+ if(compare > 0) rotateRight(entry);
+ else if(compare < 0) {
+ rotateLeft(entry.left);
+ rotateRight(entry);
+ }
+ }
+ else if(balance < -1) {
+ int compare = entry.right.getBalance();
+ if(compare < 0) rotateLeft(entry);
+ else if(compare > 0) {
+ rotateRight(entry.right);
+ rotateLeft(entry);
+ }
+ }
+ entry = entry.parent;
+ }
+ }
+
+ /** From CLR */
+ protected void fixAfterDeletion(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ if(entry != null) {
+ entry.updateHeight();
+ int balance = entry.getBalance();
+ if(balance > 1) {
+ int subBalance = entry.left.getBalance();
+ if(subBalance >= 0) rotateRight(entry);
+ else {
+ rotateLeft(entry.left);
+ rotateRight(entry);
+ }
+ }
+ else if(balance < -1)
+ {
+ int subBalance = entry.right.getBalance();
+ if(subBalance <= 0) rotateLeft(entry);
+ else {
+ rotateRight(entry.right);
+ rotateLeft(entry);
+ }
+ }
+ entry = entry.parent;
+ }
+ }
+
+ static final class AscendingSubMap KEY_VALUE_GENERIC_TYPE extends NavigableSubMap KEY_VALUE_GENERIC_TYPE {
+
+ public AscendingSubMap(AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE m, boolean fromStart, KEY_TYPE low, boolean loInclusive, boolean toEnd, KEY_TYPE high, boolean hiInclusive) {
+ super(m, fromStart, low, loInclusive, toEnd, high, hiInclusive);
+ }
+
+ @Override
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(boolean descending) { return new SubMapKeyIterator(descending); }
+ @Override
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(KEY_TYPE key) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findNode(key);
+ return entry == null || !inClosedRange(key) ? null : new SubMapKeyIterator(entry, fromStart ? null : findLowest(), toEnd ? null : findHighest());
+ }
+ @Override
+ VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE valueIterator() { return new SubMapValueIterator(false); }
+ @Override
+ ObjectListIterator entryIterator() { return new SubMapEntrySetIterator(false); }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap() {
+ if(descendingMap == null) descendingMap = new DescendingSubMapKV_BRACES(m, fromStart, low, loInclusive, toEnd, high, hiInclusive);
+ return descendingMap;
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive) {
+ if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range");
+ if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range");
+ return new AscendingSubMapKV_BRACES(m, false, fromKey, fromInclusive, false, toKey, toInclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive) {
+ if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range");
+ return new AscendingSubMapKV_BRACES(m, fromStart, low, loInclusive, false, toKey, inclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive) {
+ if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range");
+ return new AscendingSubMapKV_BRACES(m, false, fromKey, inclusive, toEnd, high, hiInclusive);
+ }
+ }
+
+ static final class DescendingSubMap KEY_VALUE_GENERIC_TYPE extends NavigableSubMap KEY_VALUE_GENERIC_TYPE {
+
+ public DescendingSubMap(AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE m, boolean fromStart, KEY_TYPE low, boolean loInclusive, boolean toEnd, KEY_TYPE high, boolean hiInclusive) {
+ super(m, fromStart, low, loInclusive, toEnd, high, hiInclusive);
+ }
+
+ @Override
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(boolean descending) {
+ LIST_ITERATOR KEY_GENERIC_TYPE iter = new SubMapKeyIterator(!descending);
+ return descending ? iter : ITERATORS.invert(iter);
+ }
+
+ @Override
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(KEY_TYPE key) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findNode(key);
+ return entry == null || !inClosedRange(key) ? null : ITERATORS.invert(new SubMapKeyIterator(entry, fromStart ? null : findLowest(), toEnd ? null : findHighest()));
+ }
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return m.comparator().reversed(); }
+
+ @Override
+ VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE valueIterator() { return VALUE_ITERATORS.invert(new SubMapValueIterator(true)); }
+
+ @Override
+ ObjectListIterator entryIterator() { return ObjectIterators.invert(new SubMapEntrySetIterator(true)); }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap() {
+ if(descendingMap == null) descendingMap = new AscendingSubMapKV_BRACES(m, fromStart, low, loInclusive, toEnd, high, hiInclusive);
+ return descendingMap;
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive) {
+ if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range");
+ if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range");
+ return new DescendingSubMapKV_BRACES(m, false, fromKey, fromInclusive, false, toKey, toInclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive) {
+ if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range");
+ return new DescendingSubMapKV_BRACES(m, fromStart, low, loInclusive, false, toKey, inclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive) {
+ if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range");
+ return new DescendingSubMapKV_BRACES(m, false, fromKey, inclusive, toEnd, high, hiInclusive);
+ }
+ }
+
+ static abstract class NavigableSubMap KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE {
+ final AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE m;
+ final KEY_TYPE low;
+ final KEY_TYPE high;
+ final boolean fromStart;
+ final boolean toEnd;
+ final boolean loInclusive;
+ final boolean hiInclusive;
+ transient NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap;
+ transient SubMapEntrySet entrySet;
+ transient KeySet KEY_VALUE_GENERIC_TYPE keySet;
+ transient SubMapValues values;
+
+ NavigableSubMap(AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE m, boolean fromStart, KEY_TYPE low, boolean loInclusive, boolean toEnd, KEY_TYPE high, boolean hiInclusive) {
+ this.m = m;
+ this.low = low;
+ this.high = high;
+ this.fromStart = fromStart;
+ this.toEnd = toEnd;
+ this.loInclusive = loInclusive;
+ this.hiInclusive = hiInclusive;
+ }
+
+ abstract LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(boolean descending);
+ abstract LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(KEY_TYPE key);
+ abstract VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE valueIterator();
+ abstract ObjectListIterator entryIterator();
+
+ @Override
+ public abstract NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap();
+ @Override
+ public abstract NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive);
+ @Override
+ public abstract NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive);
+ @Override
+ public abstract NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive);
+
+ boolean tooLow(KEY_TYPE key) { return !fromStart && (loInclusive ? m.compare(key, low) < 0 : m.compare(key, low) <= 0); }
+ boolean tooHigh(KEY_TYPE key) { return !toEnd && (hiInclusive ? m.compare(key, high) > 0 : m.compare(key, high) >= 0); }
+ boolean inRange(KEY_TYPE key) { return !tooLow(key) && !tooHigh(key); }
+ boolean inClosedRange(KEY_TYPE key) { return (fromStart || m.compare(key, low) >= 0) && (toEnd || m.compare(high, key) >= 0); }
+ boolean inRange(KEY_TYPE key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); }
+
+#if TYPE_OBJECT
+ public KEY_TYPE getDefaultMaxValue() { return m.getDefaultMaxValue(); }
+ public KEY_TYPE getDefaultMinValue() { return m.getDefaultMinValue(); }
+#else
+ @Override
+ public void setDefaultMaxValue(KEY_TYPE e) { m.setDefaultMaxValue(e); }
+ @Override
+ public KEY_TYPE getDefaultMaxValue() { return m.getDefaultMaxValue(); }
+ @Override
+ public void setDefaultMinValue(KEY_TYPE e) { m.setDefaultMinValue(e); }
+ @Override
+ public KEY_TYPE getDefaultMinValue() { return m.getDefaultMinValue(); }
+
+#endif
+ @Override
+ public ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE setDefaultReturnValue(VALUE_TYPE v) {
+ m.setDefaultReturnValue(v);
+ return this;
+ }
+
+ @Override
+ public VALUE_TYPE getDefaultReturnValue() { return m.getDefaultReturnValue(); }
+
+ @Override
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToFirst(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToLast(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return m.comparator(); }
+#if TYPE_OBJECT
+ @Override
+ public boolean containsKey(Object key) { return inRange((CLASS_TYPE)key) && m.containsKey(key); }
+#else
+ @Override
+ public boolean containsKey(KEY_TYPE key) { return inRange(key) && m.containsKey(key); }
+
+#endif
+ @Override
+ public KEY_TYPE FIRST_ENTRY_KEY() {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? getDefaultMaxValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
+ if(fromStart) return m.POLL_FIRST_ENTRY_KEY();
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = loInclusive ? m.findCeilingNode(low) : m.findHigherNode(low);
+ if(entry != null && !tooHigh(entry.key)) {
+ KEY_TYPE value = entry.key;
+ m.removeNode(entry);
+ return value;
+ }
+ return getDefaultMaxValue();
+ }
+
+ @Override
+ public KEY_TYPE LAST_ENTRY_KEY() {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? getDefaultMinValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE POLL_LAST_ENTRY_KEY() {
+ if(toEnd) return m.POLL_LAST_ENTRY_KEY();
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = hiInclusive ? m.findFloorNode(high) : m.findLowerNode(high);
+ if(entry != null && !tooLow(entry.key)) {
+ KEY_TYPE value = entry.key;
+ m.removeNode(entry);
+ return value;
+ }
+ return getDefaultMinValue();
+ }
+
+ @Override
+ public VALUE_TYPE FIRST_ENTRY_VALUE() {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? getDefaultReturnValue() : entry.value;
+ }
+
+ @Override
+ public VALUE_TYPE LAST_ENTRY_VALUE() {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? getDefaultReturnValue() : entry.value;
+ }
+
+ protected AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE findLowest() {
+ if(fromStart) return m.first;
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = loInclusive ? m.findCeilingNode(low) : m.findHigherNode(low);
+ return entry == null || tooHigh(entry.key) ? null : entry;
+ }
+
+ protected AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE findHighest() {
+ if(toEnd) return m.last;
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = hiInclusive ? m.findFloorNode(high) : m.findLowerNode(high);
+ return entry == null || tooLow(entry.key) ? null : entry;
+ }
+
+ @Override
+ public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
+ if(!inRange(key)) throw new IllegalArgumentException("key out of range");
+ return m.put(key, value);
+ }
+
+ @Override
+ public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
+ if(!inRange(key)) throw new IllegalArgumentException("key out of range");
+ return m.putIfAbsent(key, value);
+ }
+
+#if VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
+ if(!inRange(key)) throw new IllegalArgumentException("key out of range");
+ return m.addTo(key, value);
+ }
+
+#endif
+ @Override
+ public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
+ return inRange(key) ? m.GET_VALUE(key) : getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
+ return inRange(key) ? m.remove(key) : getDefaultReturnValue();
+ }
+
+#if TYPE_OBJECT && VALUE_OBJECT
+ @Override
+ public boolean remove(Object key, Object value) {
+ return inRange((CLASS_TYPE)key) && m.remove(key, value);
+ }
+
+#else
+ @Override
+ public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
+ return inRange(key) && m.remove(key, value);
+ }
+
+#endif
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new SubMapEntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet() { return navigableKeySet(); }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE navigableKeySet() {
+ if(keySet == null) keySet = new KeySetKV_BRACES(this);
+ return keySet;
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE descendingKeySet() {
+ return descendingMap().navigableKeySet();
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(values == null) values = new SubMapValues();
+ return values;
+ }
+
+ @Override
+ public int size() {
+ return (fromStart && toEnd) ? m.size() : entrySet().size();
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE firstEntry() {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lastEntry() {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirstEntry() {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ if(entry == null) return null;
+ BasicEntry KEY_VALUE_GENERIC_TYPE result = new BasicEntryKV_BRACES(entry.key, entry.value);
+ m.removeNode(entry);
+ return result;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLastEntry() {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ if(entry == null) return null;
+ BasicEntry KEY_VALUE_GENERIC_TYPE result = new BasicEntryKV_BRACES(entry.key, entry.value);
+ m.removeNode(entry);
+ return result;
+ }
+
+ @Override
+ public KEY_TYPE lowerKey(KEY_TYPE e) {
+ if(tooHigh(e)) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? getDefaultMinValue() : entry.key;
+ }
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findLowerNode(e);
+ return entry == null || tooHigh(entry.key) ? getDefaultMaxValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE floorKey(KEY_TYPE e) {
+ if(tooHigh(e)) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? getDefaultMinValue() : entry.key;
+ }
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findFloorNode(e);
+ return entry == null || tooHigh(entry.key) ? getDefaultMaxValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE ceilingKey(KEY_TYPE e) {
+ if(tooLow(e)) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? getDefaultMaxValue() : entry.key;
+ }
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findCeilingNode(e);
+ return entry == null || tooLow(entry.key) ? getDefaultMinValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE higherKey(KEY_TYPE e) {
+ if(tooLow(e)) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? getDefaultMaxValue() : entry.key;
+ }
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findHigherNode(e);
+ return entry == null || tooLow(entry.key) ? getDefaultMinValue() : entry.key;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(KEY_TYPE e) {
+ if(tooHigh(e)) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findLowerNode(e);
+ return entry == null || tooHigh(entry.key) ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(KEY_TYPE e) {
+ if(tooHigh(e)) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findFloorNode(e);
+ return entry == null || tooHigh(entry.key) ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(KEY_TYPE e) {
+ if(tooLow(e)) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findCeilingNode(e);
+ return entry == null || tooLow(entry.key) ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(KEY_TYPE e) {
+ if(tooLow(e)) {
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findHigherNode(e);
+ return entry == null || tooLow(entry.key) ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ class SubMapEntrySet extends AbstractObjectSet implements ObjectSet {
+ @Override
+ @Deprecated
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) return NavigableSubMap.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
+ return NavigableSubMap.this.containsKey(((Map.Entry, ?>)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return NavigableSubMap.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return NavigableSubMap.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+ @Override
+ public ObjectIterator iterator() { return entryIterator(); }
+ @Override
+ public int size() { return NavigableSubMap.this.size(); }
+ @Override
+ public void clear() { NavigableSubMap.this.clear(); }
+ }
+
+ final class SubMapValues extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+ @Override
+ public boolean add(VALUE_TYPE o) { throw new UnsupportedOperationException(); }
+
+#if VALUE_OBJECT
+ @Override
+ public boolean contains(Object e) {
+ return containsValue(e);
+ }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) {
+ return containsValue(e);
+ }
+
+#endif
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() { return valueIterator(); }
+
+ @Override
+ public int size() {
+ return NavigableSubMap.this.size();
+ }
+
+ @Override
+ public void clear() {
+ NavigableSubMap.this.clear();
+ }
+ }
+
+ final class SubMapEntrySetIterator extends SubMapEntryIterator implements ObjectListIterator {
+ public SubMapEntrySetIterator(boolean descending) {
+ super(descending);
+ }
+
+ public SubMapEntrySetIterator(AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry, AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE lowerFence, AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE upperFence) {
+ super(entry, lowerFence, upperFence);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() { return nextEntry(); }
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() { return previousEntry(); }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ final class SubMapKeyIterator extends SubMapEntryIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
+ public SubMapKeyIterator(boolean descending) {
+ super(descending);
+ }
+
+ public SubMapKeyIterator(AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry, AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE lowerFence, AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE upperFence) {
+ super(entry, lowerFence, upperFence);
+ }
+
+ @Override
+ public KEY_TYPE NEXT() { return nextEntry().key; }
+ @Override
+ public KEY_TYPE PREVIOUS() { return previousEntry().key; }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ final class SubMapValueIterator extends SubMapEntryIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
+ public SubMapValueIterator(boolean descending) {
+ super(descending);
+ }
+
+ public SubMapValueIterator(AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry, AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE lowerFence, AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE upperFence) {
+ super(entry, lowerFence, upperFence);
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_NEXT() { return nextEntry().value; }
+ @Override
+ public VALUE_TYPE VALUE_PREVIOUS() { return previousEntry().value; }
+
+ @Override
+ public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ abstract class SubMapEntryIterator {
+ CLASS_TYPE lowerFence;
+ CLASS_TYPE upperFence;
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE next;
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE previous;
+ AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE current;
+ int index = 0;
+
+ public SubMapEntryIterator(boolean descending) {
+ this(descending ? findHighest() : findLowest(), fromStart ? null : findLowest(), toEnd ? null : findHighest());
+ }
+
+ public SubMapEntryIterator(AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry, AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE lowerFence, AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE upperFence) {
+ next = entry;
+ previous = entry.previous();
+ this.lowerFence = lowerFence != null ? KEY_TO_OBJ(lowerFence.key) : null;
+ this.upperFence = upperFence != null ? KEY_TO_OBJ(upperFence.key) : null;
+ }
+
+ public boolean hasNext() {
+ return next != null && (upperFence == null || KEY_EQUALS(next.key, OBJ_TO_KEY(upperFence)));
+ }
+
+ public boolean hasPrevious() {
+ return previous != null && (lowerFence == null || KEY_EQUALS(next.key, OBJ_TO_KEY(lowerFence)));
+ }
+
+ public int nextIndex() {
+ return index;
+ }
+
+ public int previousIndex() {
+ return index - 1;
+ }
+
+ protected void updateNext() {
+ next = current.next();
+ }
+
+ protected void updatePrevious() {
+ previous = current.previous();
+ }
+
+ public AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ current = previous = next;
+ updateNext();
+ index++;
+ return current;
+ }
+
+ public AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE previousEntry() {
+ if(!hasPrevious()) throw new NoSuchElementException();
+ current = next = previous;
+ updatePrevious();
+ index--;
+ return current;
+ }
+
+ public void remove() {
+ if(current == null) throw new IllegalStateException();
+ if(current == previous) index--;
+ updateNext();
+ updatePrevious();
+ if(current.needsSuccessor()) next = current;
+ m.removeNode(current);
+ current = null;
+ }
+ }
+ }
+
+ private class EntrySet extends AbstractObjectSet {
+
+ @Override
+ public ObjectIterator iterator() {
+ return new EntryIterator(false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) return AVL_TREE_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
+ return AVL_TREE_MAP.this.containsKey(((Map.Entry, ?>)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return AVL_TREE_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return AVL_TREE_MAP.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return AVL_TREE_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ AVL_TREE_MAP.this.clear();
+ }
+ }
+
+ static final class KeySet KEY_VALUE_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE {
+ NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE m;
+
+ KeySet(NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE m) {
+ this.m = m;
+ }
+
+#if !TYPE_OBJECT
+ @Override
+ public void setDefaultMaxValue(KEY_TYPE e) { m.setDefaultMaxValue(e); }
+ @Override
+ public KEY_TYPE getDefaultMaxValue() { return m.getDefaultMaxValue(); }
+ @Override
+ public void setDefaultMinValue(KEY_TYPE e) { m.setDefaultMinValue(e); }
+ @Override
+ public KEY_TYPE getDefaultMinValue() { return m.getDefaultMinValue(); }
+#endif
+ @Override
+ public boolean add(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return m.comparator(); }
+ @Override
+ public KEY_TYPE lower(KEY_TYPE e) { return m.lowerKey(e); }
+ @Override
+ public KEY_TYPE floor(KEY_TYPE e) { return m.floorKey(e); }
+ @Override
+ public KEY_TYPE ceiling(KEY_TYPE e) { return m.ceilingKey(e); }
+ @Override
+ public KEY_TYPE higher(KEY_TYPE e) { return m.higherKey(e); }
+ @Override
+ public KEY_TYPE FIRST_KEY() { return m.FIRST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE POLL_FIRST_KEY() { return m.POLL_FIRST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE LAST_KEY() { return m.LAST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE POLL_LAST_KEY() { return m.POLL_LAST_ENTRY_KEY(); }
+#if TYPE_OBJECT
+ @Override
+ public boolean remove(Object o) {
+ int oldSize = m.size();
+ m.remove(o);
+ return oldSize != m.size();
+ }
+
+#else
+ @Override
+ public boolean remove(KEY_TYPE o) {
+ int oldSize = m.size();
+ m.remove(o);
+ return oldSize != m.size();
+ }
+
+#endif
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) {
+ return new KeySetKV_BRACES(m.subMap(fromElement, fromInclusive, toElement, toInclusive));
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive) {
+ return new KeySetKV_BRACES(m.headMap(toElement, inclusive));
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) {
+ return new KeySetKV_BRACES(m.tailMap(fromElement, inclusive));
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() {
+ return new KeySetKV_BRACES(m.descendingMap());
+ }
+
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
+ if(m instanceof AVL_TREE_MAP) return ((AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE)m).keyIterator(false);
+ return ((NavigableSubMap KEY_VALUE_GENERIC_TYPE)m).keyIterator(false);
+ }
+
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
+ if(m instanceof AVL_TREE_MAP) return ((AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE)m).keyIterator(fromElement);
+ return ((NavigableSubMap KEY_VALUE_GENERIC_TYPE)m).keyIterator(fromElement);
+ }
+
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() {
+ if(m instanceof AVL_TREE_MAP) return ((AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE)m).keyIterator(true);
+ return ((NavigableSubMap KEY_VALUE_GENERIC_TYPE)m).keyIterator(true);
+ }
+
+ @Override
+ public int size() {
+ return m.size();
+ }
+
+ @Override
+ public void clear() {
+ m.clear();
+ }
+ }
+
+ final class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+
+ @Override
+ public boolean add(VALUE_TYPE o) { throw new UnsupportedOperationException(); }
+
+#if VALUE_OBJECT
+ @Override
+ public boolean contains(Object e) {
+ return containsValue(e);
+ }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) {
+ return containsValue(e);
+ }
+
+#endif
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() { return new ValueIterator(false); }
+
+ @Override
+ public int size() {
+ return AVL_TREE_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ AVL_TREE_MAP.this.clear();
+ }
+ }
+
+ final class EntryIterator extends MapEntryIterator implements ObjectListIterator {
+
+ public EntryIterator(boolean descending) {
+ super(descending);
+ }
+
+ public EntryIterator(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ super(entry);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ return nextEntry();
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ return previousEntry();
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ final class KeyIterator extends MapEntryIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
+
+ public KeyIterator(boolean descending) {
+ super(descending);
+ }
+
+ public KeyIterator(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ super(entry);
+ }
+
+ @Override
+ public KEY_TYPE PREVIOUS() { return previousEntry().key; }
+ @Override
+ public KEY_TYPE NEXT() { return nextEntry().key; }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ final class ValueIterator extends MapEntryIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
+
+ public ValueIterator(boolean descending) {
+ super(descending);
+ }
+
+ public ValueIterator(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ super(entry);
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_PREVIOUS() {
+ return previousEntry().value;
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return nextEntry().value;
+ }
+
+ @Override
+ public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ abstract class MapEntryIterator {
+ Entry KEY_VALUE_GENERIC_TYPE next;
+ Entry KEY_VALUE_GENERIC_TYPE previous;
+ Entry KEY_VALUE_GENERIC_TYPE current;
+ int index = 0;
+
+ public MapEntryIterator(boolean descending) {
+ if(descending) previous = last;
+ else next = first;
+ }
+
+ public MapEntryIterator(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ next = entry;
+ previous = entry.previous();
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public boolean hasPrevious() {
+ return previous != null;
+ }
+
+ public int nextIndex() {
+ return index;
+ }
+
+ public int previousIndex() {
+ return index - 1;
+ }
+
+ protected void updateNext() {
+ next = current.next();
+ }
+
+ protected void updatePrevious() {
+ previous = current.previous();
+ }
+
+ public Entry KEY_VALUE_GENERIC_TYPE nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ current = previous = next;
+ updateNext();
+ index++;
+ return current;
+ }
+
+ public Entry KEY_VALUE_GENERIC_TYPE previousEntry() {
+ if(!hasPrevious()) throw new NoSuchElementException();
+ current = next = previous;
+ updatePrevious();
+ index--;
+ return current;
+ }
+
+ public void remove() {
+ if(current == null) throw new IllegalStateException();
+ if(current == previous) index--;
+ updateNext();
+ updatePrevious();
+ if(current.needsSuccessor()) next = current;
+ removeNode(current);
+ current = null;
+ }
+ }
+
+ private static final class Entry KEY_VALUE_GENERIC_TYPE implements MAP.Entry KEY_VALUE_GENERIC_TYPE
+ {
+ KEY_TYPE key;
+ VALUE_TYPE value;
+ int state;
+ Entry KEY_VALUE_GENERIC_TYPE parent;
+ Entry KEY_VALUE_GENERIC_TYPE left;
+ Entry KEY_VALUE_GENERIC_TYPE right;
+
+ Entry(KEY_TYPE key, VALUE_TYPE value, Entry KEY_VALUE_GENERIC_TYPE parent) {
+ this.key = key;
+ this.value = value;
+ this.parent = parent;
+ }
+
+ @Override
+ public KEY_TYPE ENTRY_KEY() {
+ return key;
+ }
+
+ @Override
+ public VALUE_TYPE ENTRY_VALUE() {
+ return value;
+ }
+
+ @Override
+ public VALUE_TYPE setValue(VALUE_TYPE value) {
+ VALUE_TYPE oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+#if VALUE_PRIMITIVES
+ VALUE_TYPE addTo(VALUE_TYPE value) {
+ VALUE_TYPE oldValue = this.value;
+ this.value += value;
+ return oldValue;
+ }
+
+#endif
+ int getHeight() { return state; }
+
+ void updateHeight() { state = (1 + Math.max(left == null ? 0 : left.getHeight(), right == null ? 0 : right.getHeight())); }
+
+ int getBalance() { return (left == null ? 0 : left.getHeight()) - (right == null ? 0 : right.getBalance()); }
+
+ boolean needsSuccessor() { return left != null && right != null; }
+
+ boolean replace(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ if(entry != null) entry.parent = parent;
+ if(parent != null) {
+ if(parent.left == this) parent.left = entry;
+ else parent.right = entry;
+ }
+ return parent == null;
+ }
+
+ Entry KEY_VALUE_GENERIC_TYPE next() {
+ if(right != null) {
+ Entry KEY_VALUE_GENERIC_TYPE parent = right;
+ while(parent.left != null) parent = parent.left;
+ return parent;
+ }
+ Entry KEY_VALUE_GENERIC_TYPE parent = this.parent;
+ Entry KEY_VALUE_GENERIC_TYPE control = this;
+ while(parent != null && control == parent.right) {
+ control = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+
+ Entry KEY_VALUE_GENERIC_TYPE previous() {
+ if(left != null) {
+ Entry KEY_VALUE_GENERIC_TYPE parent = left;
+ while(parent.right != null) parent = parent.right;
+ return parent;
+ }
+ Entry KEY_VALUE_GENERIC_TYPE parent = this.parent;
+ Entry KEY_VALUE_GENERIC_TYPE control = this;
+ while(parent != null && control == parent.left) {
+ control = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/impl/tree/RBTreeMap.template b/src/main/resources/speiger/assets/collections/templates/maps/impl/tree/RBTreeMap.template
new file mode 100644
index 0000000..4117087
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/impl/tree/RBTreeMap.template
@@ -0,0 +1,1750 @@
+package speiger.src.collections.PACKAGE.maps.impl.tree;
+
+import java.util.Map;
+#if TYPE_OBJECT
+import java.util.Comparator;
+import java.util.Objects;
+#endif
+import java.util.NoSuchElementException;
+
+import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.functions.COMPARATOR;
+#endif
+import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
+import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
+import speiger.src.collections.PACKAGE.maps.interfaces.NAVIGABLE_MAP;
+import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
+import speiger.src.collections.PACKAGE.sets.NAVIGABLE_SET;
+import speiger.src.collections.PACKAGE.sets.SET;
+import speiger.src.collections.PACKAGE.sets.SORTED_SET;
+import speiger.src.collections.PACKAGE.utils.ITERATORS;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
+#if !SAME_TYPE
+import speiger.src.collections.VALUE_PACKAGE.lists.VALUE_LIST_ITERATOR;
+import speiger.src.collections.VALUE_PACKAGE.utils.VALUE_ITERATORS;
+#endif
+#if !TYPE_OBJECT && !VALUE_OBJECT
+import speiger.src.collections.objects.lists.ObjectListIterator;
+import speiger.src.collections.objects.utils.ObjectIterators;
+#endif
+#if !VALUE_OBJECT
+import speiger.src.collections.objects.collections.ObjectIterator;
+#endif
+#if !TYPE_OBJECT
+import speiger.src.collections.objects.sets.AbstractObjectSet;
+import speiger.src.collections.objects.sets.ObjectSet;
+#endif
+
+public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE
+{
+ protected transient Entry KEY_VALUE_GENERIC_TYPE tree;
+ protected transient Entry KEY_VALUE_GENERIC_TYPE first;
+ protected transient Entry KEY_VALUE_GENERIC_TYPE last;
+ protected int size = 0;
+ protected transient COMPARATOR KEY_GENERIC_TYPE comparator;
+
+#if TYPE_OBJECT
+ protected KEY_TYPE defaultMaxNotFound = null;
+ protected KEY_TYPE defaultMinNotFound = null;
+#else
+ protected KEY_TYPE defaultMaxNotFound = CLASS_TYPE.MIN_VALUE;
+ protected KEY_TYPE defaultMinNotFound = CLASS_TYPE.MAX_VALUE;
+#endif
+
+ protected NAVIGABLE_SET KEY_GENERIC_TYPE keySet;
+ protected VALUE_COLLECTION VALUE_GENERIC_TYPE values;
+ protected ObjectSet entrySet;
+#if TYPE_OBJECT
+ public KEY_TYPE getDefaultMaxValue() { return defaultMaxNotFound; }
+ public KEY_TYPE getDefaultMinValue() { return defaultMinNotFound; }
+
+#else
+ @Override
+ public void setDefaultMaxValue(KEY_TYPE value) { defaultMaxNotFound = value; }
+ @Override
+ public KEY_TYPE getDefaultMaxValue() { return defaultMaxNotFound; }
+ @Override
+ public void setDefaultMinValue(KEY_TYPE value) { defaultMinNotFound = value; }
+ @Override
+ public KEY_TYPE getDefaultMinValue() { return defaultMinNotFound; }
+
+#endif
+ @Override
+ public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
+ if(tree == null) {
+ tree = first = last = new EntryKV_BRACES(key, value, null);
+ size++;
+ return getDefaultReturnValue();
+ }
+ int compare = 0;
+ Entry KEY_VALUE_GENERIC_TYPE parent = tree;
+ while(true) {
+ if((compare = compare(key, parent.key)) == 0) return parent.setValue(value);
+ if(compare < 0) {
+ if(parent.left == null) break;
+ parent = parent.left;
+ }
+ else if(compare > 0) {
+ if(parent.right == null) break;
+ parent = parent.right;
+ }
+ }
+ Entry KEY_VALUE_GENERIC_TYPE adding = new EntryKV_BRACES(key, value, parent);
+ if(compare < 0) {
+ parent.left = adding;
+ if(parent == first) first = adding;
+ }
+ else {
+ parent.right = adding;
+ if(parent == last) last = adding;
+ }
+ fixAfterInsertion(adding);
+ size++;
+ return getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
+ if(tree == null) {
+ tree = first = last = new EntryKV_BRACES(key, value, null);
+ size++;
+ return getDefaultReturnValue();
+ }
+ int compare = 0;
+ Entry KEY_VALUE_GENERIC_TYPE parent = tree;
+ while(true) {
+ if((compare = compare(key, parent.key)) == 0) return parent.value;
+ if(compare < 0) {
+ if(parent.left == null) break;
+ parent = parent.left;
+ }
+ else if(compare > 0) {
+ if(parent.right == null) break;
+ parent = parent.right;
+ }
+ }
+ Entry KEY_VALUE_GENERIC_TYPE adding = new EntryKV_BRACES(key, value, parent);
+ if(compare < 0) {
+ parent.left = adding;
+ if(parent == first) first = adding;
+ }
+ else {
+ parent.right = adding;
+ if(parent == last) last = adding;
+ }
+ fixAfterInsertion(adding);
+ size++;
+ return getDefaultReturnValue();
+ }
+
+#if VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
+ if(tree == null) {
+ tree = first = last = new EntryKV_BRACES(key, value, null);
+ size++;
+ return getDefaultReturnValue();
+ }
+ int compare = 0;
+ Entry KEY_VALUE_GENERIC_TYPE parent = tree;
+ while(true) {
+ if((compare = compare(key, parent.key)) == 0) return parent.addTo(value);
+ if(compare < 0) {
+ if(parent.left == null) break;
+ parent = parent.left;
+ }
+ else if(compare > 0) {
+ if(parent.right == null) break;
+ parent = parent.right;
+ }
+ }
+ Entry KEY_VALUE_GENERIC_TYPE adding = new EntryKV_BRACES(key, value, parent);
+ if(compare < 0) {
+ parent.left = adding;
+ if(parent == first) first = adding;
+ }
+ else {
+ parent.right = adding;
+ if(parent == last) last = adding;
+ }
+ fixAfterInsertion(adding);
+ size++;
+ return getDefaultReturnValue();
+ }
+
+#endif
+ @Override
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToFirst(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToLast(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return comparator; }
+
+#if TYPE_OBJECT
+ @Override
+ public boolean containsKey(Object key) {
+ return findNode((KEY_TYPE)key) != null;
+ }
+
+#else
+ @Override
+ public boolean containsKey(KEY_TYPE key) {
+ return findNode(key) != null;
+ }
+
+#endif
+ @Override
+ public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findNode(key);
+ return node == null ? getDefaultReturnValue() : node.value;
+ }
+
+#if TYPE_OBJECT
+ @Override
+ public VALUE_TYPE getOrDefault(Object key, VALUE_TYPE defaultValue) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findNode((CLASS_TYPE)key);
+ return node == null ? defaultValue : node.value;
+ }
+
+#else
+ @Override
+ public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findNode(key);
+ return node == null ? defaultValue : node.value;
+ }
+
+#endif
+ @Override
+ public KEY_TYPE FIRST_ENTRY_KEY() {
+ if(tree == null) throw new NoSuchElementException();
+ return first.key;
+ }
+
+ @Override
+ public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
+ if(tree == null) throw new NoSuchElementException();
+ KEY_TYPE result = first.key;
+ removeNode(first);
+ return result;
+ }
+
+ @Override
+ public KEY_TYPE LAST_ENTRY_KEY() {
+ if(tree == null) throw new NoSuchElementException();
+ return last.key;
+ }
+
+ @Override
+ public KEY_TYPE POLL_LAST_ENTRY_KEY() {
+ if(tree == null) throw new NoSuchElementException();
+ KEY_TYPE result = last.key;
+ removeNode(last);
+ return result;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE firstEntry() {
+ if(tree == null) throw new NoSuchElementException();
+ return new BasicEntryKV_BRACES(first.key, first.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lastEntry() {
+ if(tree == null) throw new NoSuchElementException();
+ return new BasicEntryKV_BRACES(last.key, last.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirstEntry() {
+ if(tree == null) throw new NoSuchElementException();
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(first.key, first.value);
+ removeNode(first);
+ return entry;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLastEntry() {
+ if(tree == null) throw new NoSuchElementException();
+ BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(last.key, last.value);
+ removeNode(last);
+ return entry;
+ }
+
+ @Override
+ public VALUE_TYPE FIRST_ENTRY_VALUE() {
+ if(tree == null) throw new NoSuchElementException();
+ return first.value;
+ }
+
+ @Override
+ public VALUE_TYPE LAST_ENTRY_VALUE() {
+ if(tree == null) throw new NoSuchElementException();
+ return last.value;
+ }
+
+ @Override
+ public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
+ if(entry == null) return getDefaultReturnValue();
+ VALUE_TYPE value = entry.value;
+ removeNode(entry);
+ return value;
+ }
+
+#if TYPE_OBJECT && VALUE_OBJECT
+ @Override
+ public boolean remove(Object key, Object value) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = findNode((CLASS_TYPE)key);
+ if(entry == null || !Objects.equals(value, entry.value)) return false;
+ removeNode(entry);
+ return true;
+ }
+
+#else
+ @Override
+ public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
+ if(entry == null || entry.value != value) return false;
+ removeNode(entry);
+ return true;
+ }
+
+#endif
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(boolean descending) {
+ LIST_ITERATOR KEY_GENERIC_TYPE iter = new KeyIterator(descending);
+ return descending ? ITERATORS.invert(iter) : iter;
+ }
+
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(KEY_TYPE key) {
+ return new KeyIterator(findNode(key));
+ }
+
+ @Override
+ public SORTED_SET KEY_GENERIC_TYPE keySet() {
+ return navigableKeySet();
+ }
+
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new EntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(values == null) values = new Values();
+ return values;
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE navigableKeySet() {
+ if(keySet == null) keySet = new KeySetKV_BRACES(this);
+ return keySet;
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap() {
+ return new DescendingSubMapKV_BRACES(this, true, EMPTY_KEY_VALUE, true, true, EMPTY_KEY_VALUE, true);
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE descendingKeySet() {
+ return descendingMap().navigableKeySet();
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive) {
+ return new AscendingSubMapKV_BRACES(this, false, fromKey, fromInclusive, false, toKey, toInclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive) {
+ return new AscendingSubMapKV_BRACES(this, true, EMPTY_KEY_VALUE, true, false, toKey, inclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive) {
+ return new AscendingSubMapKV_BRACES(this, false, fromKey, inclusive, true, EMPTY_KEY_VALUE, true);
+ }
+
+ @Override
+ public KEY_TYPE lowerKey(KEY_TYPE e) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findLowerNode(e);
+ return node != null ? node.key : defaultMinNotFound;
+ }
+
+ @Override
+ public KEY_TYPE floorKey(KEY_TYPE e) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findFloorNode(e);
+ return node != null ? node.key : defaultMinNotFound;
+ }
+
+ @Override
+ public KEY_TYPE higherKey(KEY_TYPE e) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findHigherNode(e);
+ return node != null ? node.key : defaultMaxNotFound;
+ }
+
+ @Override
+ public KEY_TYPE ceilingKey(KEY_TYPE e) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findCeilingNode(e);
+ return node != null ? node.key : defaultMaxNotFound;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findLowerNode(key);
+ return node != null ? new BasicEntryKV_BRACES(node.key, node.value) : null;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findHigherNode(key);
+ return node != null ? new BasicEntryKV_BRACES(node.key, node.value) : null;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findFloorNode(key);
+ return node != null ? new BasicEntryKV_BRACES(node.key, node.value) : null;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = findCeilingNode(key);
+ return node != null ? new BasicEntryKV_BRACES(node.key, node.value) : null;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findLowerNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = tree;
+ while(entry != null) {
+ if(compare(key, entry.key) > 0) {
+ if(entry.right != null) entry = entry.right;
+ else return entry;
+ }
+ else {
+ if(entry.left != null) entry = entry.left;
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ while(parent != null && parent.left == entry) {
+ entry = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ }
+ }
+ return null;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findFloorNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = tree;
+ int compare;
+ while(entry != null) {
+ if((compare = compare(key, entry.key)) > 0) {
+ if(entry.right == null) break;
+ entry = entry.right;
+ continue;
+ }
+ else if(compare < 0) {
+ if(entry.left != null) entry = entry.left;
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ while(parent != null && parent.left == entry) {
+ entry = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ continue;
+ }
+ break;
+ }
+ return entry;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findCeilingNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = tree;
+ int compare;
+ while(entry != null) {
+ if((compare = compare(key, entry.key)) < 0) {
+ if(entry.left == null) break;
+ entry = entry.left;
+ continue;
+ }
+ else if(compare > 0) {
+ if(entry.right != null) entry = entry.right;
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ while(parent != null && parent.right == entry) {
+ entry = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ continue;
+ }
+ break;
+ }
+ return entry;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findHigherNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE entry = tree;
+ while(entry != null) {
+ if(compare(key, entry.key) < 0) {
+ if(entry.left != null) entry = entry.left;
+ else return entry;
+ }
+ else {
+ if(entry.right != null) entry = entry.right;
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ while(parent != null && parent.right == entry) {
+ entry = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ }
+ }
+ return null;
+ }
+
+ protected Entry KEY_VALUE_GENERIC_TYPE findNode(KEY_TYPE key) {
+ Entry KEY_VALUE_GENERIC_TYPE node = tree;
+ int compare;
+ while(node != null) {
+ if((compare = compare(key, node.key)) == 0) return node;
+ if(compare < 0) node = node.left;
+ else node = node.right;
+ }
+ return null;
+ }
+
+ protected void removeNode(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ size--;
+ if(entry.needsSuccessor()) {
+ Entry KEY_VALUE_GENERIC_TYPE successor = entry.next();
+ entry.key = successor.key;
+ entry.value = successor.value;
+ entry = successor;
+ }
+ Entry KEY_VALUE_GENERIC_TYPE replacement = entry.left != null ? entry.left : entry.right;
+ if(replacement != null) {
+ if(entry.replace(replacement)) tree = replacement;
+ if(entry == first) first = replacement;
+ if(entry == last) last = entry.right != null ? entry.right : replacement;
+ entry.left = entry.right = entry.parent = null;
+ if(entry.isBlack()) fixAfterDeletion(replacement);
+ }
+ else if(entry.parent == null) tree = first = last = null;
+ else {
+ if(entry.isBlack())
+ fixAfterDeletion(entry);
+ entry.replace(null);
+ if(entry.parent != null) {
+ Entry KEY_VALUE_GENERIC_TYPE parent = entry.parent;
+ if(entry == first) first = parent.left != null ? parent.left : parent;
+ if(entry == last) last = entry.right != null ? parent.right : parent;
+ }
+ entry.parent = null;
+ }
+ }
+
+ 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); }
+ protected static GENERIC_KEY_VALUE_BRACES void setBlack(Entry KEY_VALUE_GENERIC_TYPE p, boolean c) { if(p != null) p.setBlack(c); }
+ protected static GENERIC_KEY_VALUE_BRACES Entry KEY_VALUE_GENERIC_TYPE leftOf(Entry KEY_VALUE_GENERIC_TYPE p) { return p == null ? null : p.left; }
+ protected static GENERIC_KEY_VALUE_BRACES Entry KEY_VALUE_GENERIC_TYPE rightOf(Entry KEY_VALUE_GENERIC_TYPE p) { return (p == null) ? null : p.right; }
+
+ /** From CLR */
+ protected void rotateLeft(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ if(entry != null) {
+ Entry KEY_VALUE_GENERIC_TYPE right = entry.right;
+ entry.right = right.left;
+ if(right.left != null) right.left.parent = entry;
+ right.parent = entry.parent;
+ if(entry.parent == null) tree = right;
+ else if(entry.parent.left == entry) entry.parent.left = right;
+ else entry.parent.right = right;
+ right.left = entry;
+ entry.parent = right;
+ }
+ }
+
+ /** From CLR */
+ protected void rotateRight(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ if(entry != null) {
+ Entry KEY_VALUE_GENERIC_TYPE left = entry.left;
+ entry.left = left.right;
+ if(left.right != null) left.right.parent = entry;
+ left.parent = entry.parent;
+ if(entry.parent == null) tree = left;
+ else if(entry.parent.right == entry) entry.parent.right = left;
+ else entry.parent.left = left;
+ left.right = entry;
+ entry.parent = left;
+ }
+ }
+
+ /** From CLR */
+ protected void fixAfterInsertion(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ entry.setBlack(false);
+ while(entry != null && entry != tree && !entry.parent.isBlack()) {
+ if(parentOf(entry) == leftOf(parentOf(parentOf(entry)))) {
+ Entry KEY_VALUE_GENERIC_TYPE y = rightOf(parentOf(parentOf(entry)));
+ if(!isBlack(y)) {
+ setBlack(parentOf(entry), true);
+ setBlack(y, true);
+ setBlack(parentOf(parentOf(entry)), false);
+ entry = parentOf(parentOf(entry));
+ }
+ else {
+ if(entry == rightOf(parentOf(entry))) {
+ entry = parentOf(entry);
+ rotateLeft(entry);
+ }
+ setBlack(parentOf(entry), true);
+ setBlack(parentOf(parentOf(entry)), false);
+ rotateRight(parentOf(parentOf(entry)));
+ }
+ }
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE y = leftOf(parentOf(parentOf(entry)));
+ if(!isBlack(y)) {
+ setBlack(parentOf(entry), true);
+ setBlack(y, true);
+ setBlack(parentOf(parentOf(entry)), false);
+ entry = parentOf(parentOf(entry));
+ }
+ else {
+ if(entry == leftOf(parentOf(entry))) {
+ entry = parentOf(entry);
+ rotateRight(entry);
+ }
+ setBlack(parentOf(entry), true);
+ setBlack(parentOf(parentOf(entry)), false);
+ rotateLeft(parentOf(parentOf(entry)));
+ }
+ }
+ }
+ tree.setBlack(true);
+ }
+
+ /** From CLR */
+ protected void fixAfterDeletion(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ while(entry != tree && isBlack(entry)) {
+ if(entry == leftOf(parentOf(entry))) {
+ Entry KEY_VALUE_GENERIC_TYPE sib = rightOf(parentOf(entry));
+ if(!isBlack(sib)) {
+ setBlack(sib, true);
+ setBlack(parentOf(entry), false);
+ rotateLeft(parentOf(entry));
+ sib = rightOf(parentOf(entry));
+ }
+ if(isBlack(leftOf(sib)) && isBlack(rightOf(sib))) {
+ setBlack(sib, false);
+ entry = parentOf(entry);
+ }
+ else {
+ if(isBlack(rightOf(sib))) {
+ setBlack(leftOf(sib), true);
+ setBlack(sib, false);
+ rotateRight(sib);
+ sib = rightOf(parentOf(entry));
+ }
+ setBlack(sib, isBlack(parentOf(entry)));
+ setBlack(parentOf(entry), true);
+ setBlack(rightOf(sib), true);
+ rotateLeft(parentOf(entry));
+ entry = tree;
+ }
+ }
+ else {
+ Entry KEY_VALUE_GENERIC_TYPE sib = leftOf(parentOf(entry));
+ if(!isBlack(sib)) {
+ setBlack(sib, true);
+ setBlack(parentOf(entry), false);
+ rotateRight(parentOf(entry));
+ sib = leftOf(parentOf(entry));
+ }
+ if(isBlack(rightOf(sib)) && isBlack(leftOf(sib))) {
+ setBlack(sib, false);
+ entry = parentOf(entry);
+ }
+ else {
+ if(isBlack(leftOf(sib))) {
+ setBlack(rightOf(sib), true);
+ setBlack(sib, false);
+ rotateLeft(sib);
+ sib = leftOf(parentOf(entry));
+ }
+ setBlack(sib, isBlack(parentOf(entry)));
+ setBlack(parentOf(entry), true);
+ setBlack(leftOf(sib), true);
+ rotateRight(parentOf(entry));
+ entry = tree;
+ }
+ }
+ }
+ setBlack(entry, true);
+ }
+
+ static final class AscendingSubMap KEY_VALUE_GENERIC_TYPE extends NavigableSubMap KEY_VALUE_GENERIC_TYPE {
+
+ public AscendingSubMap(RB_TREE_MAP KEY_VALUE_GENERIC_TYPE m, boolean fromStart, KEY_TYPE low, boolean loInclusive, boolean toEnd, KEY_TYPE high, boolean hiInclusive) {
+ super(m, fromStart, low, loInclusive, toEnd, high, hiInclusive);
+ }
+
+ @Override
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(boolean descending) { return new SubMapKeyIterator(descending); }
+ @Override
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(KEY_TYPE key) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findNode(key);
+ return entry == null || !inClosedRange(key) ? null : new SubMapKeyIterator(entry, fromStart ? null : findLowest(), toEnd ? null : findHighest());
+ }
+ @Override
+ VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE valueIterator() { return new SubMapValueIterator(false); }
+ @Override
+ ObjectListIterator entryIterator() { return new SubMapEntrySetIterator(false); }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap() {
+ if(descendingMap == null) descendingMap = new DescendingSubMapKV_BRACES(m, fromStart, low, loInclusive, toEnd, high, hiInclusive);
+ return descendingMap;
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive) {
+ if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range");
+ if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range");
+ return new AscendingSubMapKV_BRACES(m, false, fromKey, fromInclusive, false, toKey, toInclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive) {
+ if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range");
+ return new AscendingSubMapKV_BRACES(m, fromStart, low, loInclusive, false, toKey, inclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive) {
+ if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range");
+ return new AscendingSubMapKV_BRACES(m, false, fromKey, inclusive, toEnd, high, hiInclusive);
+ }
+ }
+
+ static final class DescendingSubMap KEY_VALUE_GENERIC_TYPE extends NavigableSubMap KEY_VALUE_GENERIC_TYPE {
+
+ public DescendingSubMap(RB_TREE_MAP KEY_VALUE_GENERIC_TYPE m, boolean fromStart, KEY_TYPE low, boolean loInclusive, boolean toEnd, KEY_TYPE high, boolean hiInclusive) {
+ super(m, fromStart, low, loInclusive, toEnd, high, hiInclusive);
+ }
+
+ @Override
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(boolean descending) {
+ LIST_ITERATOR KEY_GENERIC_TYPE iter = new SubMapKeyIterator(!descending);
+ return descending ? iter : ITERATORS.invert(iter);
+ }
+
+ @Override
+ LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(KEY_TYPE key) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findNode(key);
+ return entry == null || !inClosedRange(key) ? null : ITERATORS.invert(new SubMapKeyIterator(entry, fromStart ? null : findLowest(), toEnd ? null : findHighest()));
+ }
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return m.comparator().reversed(); }
+
+ @Override
+ VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE valueIterator() { return VALUE_ITERATORS.invert(new SubMapValueIterator(true)); }
+
+ @Override
+ ObjectListIterator entryIterator() { return ObjectIterators.invert(new SubMapEntrySetIterator(true)); }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap() {
+ if(descendingMap == null) descendingMap = new AscendingSubMapKV_BRACES(m, fromStart, low, loInclusive, toEnd, high, hiInclusive);
+ return descendingMap;
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive) {
+ if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range");
+ if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range");
+ return new DescendingSubMapKV_BRACES(m, false, fromKey, fromInclusive, false, toKey, toInclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive) {
+ if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range");
+ return new DescendingSubMapKV_BRACES(m, fromStart, low, loInclusive, false, toKey, inclusive);
+ }
+
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive) {
+ if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range");
+ return new DescendingSubMapKV_BRACES(m, false, fromKey, inclusive, toEnd, high, hiInclusive);
+ }
+ }
+
+ static abstract class NavigableSubMap KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE {
+ final RB_TREE_MAP KEY_VALUE_GENERIC_TYPE m;
+ final KEY_TYPE low;
+ final KEY_TYPE high;
+ final boolean fromStart;
+ final boolean toEnd;
+ final boolean loInclusive;
+ final boolean hiInclusive;
+ transient NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap;
+ transient SubMapEntrySet entrySet;
+ transient KeySet KEY_VALUE_GENERIC_TYPE keySet;
+ transient SubMapValues values;
+
+ NavigableSubMap(RB_TREE_MAP KEY_VALUE_GENERIC_TYPE m, boolean fromStart, KEY_TYPE low, boolean loInclusive, boolean toEnd, KEY_TYPE high, boolean hiInclusive) {
+ this.m = m;
+ this.low = low;
+ this.high = high;
+ this.fromStart = fromStart;
+ this.toEnd = toEnd;
+ this.loInclusive = loInclusive;
+ this.hiInclusive = hiInclusive;
+ }
+
+ abstract LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(boolean descending);
+ abstract LIST_ITERATOR KEY_GENERIC_TYPE keyIterator(KEY_TYPE key);
+ abstract VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE valueIterator();
+ abstract ObjectListIterator entryIterator();
+
+ @Override
+ public abstract NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap();
+ @Override
+ public abstract NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive);
+ @Override
+ public abstract NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive);
+ @Override
+ public abstract NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive);
+
+ boolean tooLow(KEY_TYPE key) { return !fromStart && (loInclusive ? m.compare(key, low) < 0 : m.compare(key, low) <= 0); }
+ boolean tooHigh(KEY_TYPE key) { return !toEnd && (hiInclusive ? m.compare(key, high) > 0 : m.compare(key, high) >= 0); }
+ boolean inRange(KEY_TYPE key) { return !tooLow(key) && !tooHigh(key); }
+ boolean inClosedRange(KEY_TYPE key) { return (fromStart || m.compare(key, low) >= 0) && (toEnd || m.compare(high, key) >= 0); }
+ boolean inRange(KEY_TYPE key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); }
+
+#if TYPE_OBJECT
+ public KEY_TYPE getDefaultMaxValue() { return m.getDefaultMaxValue(); }
+ public KEY_TYPE getDefaultMinValue() { return m.getDefaultMinValue(); }
+#else
+ @Override
+ public void setDefaultMaxValue(KEY_TYPE e) { m.setDefaultMaxValue(e); }
+ @Override
+ public KEY_TYPE getDefaultMaxValue() { return m.getDefaultMaxValue(); }
+ @Override
+ public void setDefaultMinValue(KEY_TYPE e) { m.setDefaultMinValue(e); }
+ @Override
+ public KEY_TYPE getDefaultMinValue() { return m.getDefaultMinValue(); }
+
+#endif
+ @Override
+ public ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE setDefaultReturnValue(VALUE_TYPE v) {
+ m.setDefaultReturnValue(v);
+ return this;
+ }
+
+ @Override
+ public VALUE_TYPE getDefaultReturnValue() { return m.getDefaultReturnValue(); }
+
+ @Override
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToFirst(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToLast(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) { throw new UnsupportedOperationException(); }
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return m.comparator(); }
+#if TYPE_OBJECT
+ @Override
+ public boolean containsKey(Object key) { return inRange((CLASS_TYPE)key) && m.containsKey(key); }
+#else
+ @Override
+ public boolean containsKey(KEY_TYPE key) { return inRange(key) && m.containsKey(key); }
+
+#endif
+ @Override
+ public KEY_TYPE FIRST_ENTRY_KEY() {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? getDefaultMaxValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
+ if(fromStart) return m.POLL_FIRST_ENTRY_KEY();
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = loInclusive ? m.findCeilingNode(low) : m.findHigherNode(low);
+ if(entry != null && !tooHigh(entry.key)) {
+ KEY_TYPE value = entry.key;
+ m.removeNode(entry);
+ return value;
+ }
+ return getDefaultMaxValue();
+ }
+
+ @Override
+ public KEY_TYPE LAST_ENTRY_KEY() {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? getDefaultMinValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE POLL_LAST_ENTRY_KEY() {
+ if(toEnd) return m.POLL_LAST_ENTRY_KEY();
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = hiInclusive ? m.findFloorNode(high) : m.findLowerNode(high);
+ if(entry != null && !tooLow(entry.key)) {
+ KEY_TYPE value = entry.key;
+ m.removeNode(entry);
+ return value;
+ }
+ return getDefaultMinValue();
+ }
+
+ @Override
+ public VALUE_TYPE FIRST_ENTRY_VALUE() {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? getDefaultReturnValue() : entry.value;
+ }
+
+ @Override
+ public VALUE_TYPE LAST_ENTRY_VALUE() {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? getDefaultReturnValue() : entry.value;
+ }
+
+ protected RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE findLowest() {
+ if(fromStart) return m.first;
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = loInclusive ? m.findCeilingNode(low) : m.findHigherNode(low);
+ return entry == null || tooHigh(entry.key) ? null : entry;
+ }
+
+ protected RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE findHighest() {
+ if(toEnd) return m.last;
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = hiInclusive ? m.findFloorNode(high) : m.findLowerNode(high);
+ return entry == null || tooLow(entry.key) ? null : entry;
+ }
+
+ @Override
+ public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
+ if(!inRange(key)) throw new IllegalArgumentException("key out of range");
+ return m.put(key, value);
+ }
+
+ @Override
+ public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
+ if(!inRange(key)) throw new IllegalArgumentException("key out of range");
+ return m.putIfAbsent(key, value);
+ }
+
+#if VALUE_PRIMITIVES
+ @Override
+ public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
+ if(!inRange(key)) throw new IllegalArgumentException("key out of range");
+ return m.addTo(key, value);
+ }
+
+#endif
+ @Override
+ public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
+ return inRange(key) ? m.GET_VALUE(key) : getDefaultReturnValue();
+ }
+
+ @Override
+ public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
+ return inRange(key) ? m.remove(key) : getDefaultReturnValue();
+ }
+
+#if TYPE_OBJECT && VALUE_OBJECT
+ @Override
+ public boolean remove(Object key, Object value) {
+ return inRange((CLASS_TYPE)key) && m.remove(key, value);
+ }
+
+#else
+ @Override
+ public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
+ return inRange(key) && m.remove(key, value);
+ }
+
+#endif
+ @Override
+ public ObjectSet ENTRY_SET() {
+ if(entrySet == null) entrySet = new SubMapEntrySet();
+ return entrySet;
+ }
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet() { return navigableKeySet(); }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE navigableKeySet() {
+ if(keySet == null) keySet = new KeySetKV_BRACES(this);
+ return keySet;
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE descendingKeySet() {
+ return descendingMap().navigableKeySet();
+ }
+
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
+ if(values == null) values = new SubMapValues();
+ return values;
+ }
+
+ @Override
+ public int size() {
+ return (fromStart && toEnd) ? m.size() : entrySet().size();
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE firstEntry() {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lastEntry() {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirstEntry() {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ if(entry == null) return null;
+ BasicEntry KEY_VALUE_GENERIC_TYPE result = new BasicEntryKV_BRACES(entry.key, entry.value);
+ m.removeNode(entry);
+ return result;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLastEntry() {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ if(entry == null) return null;
+ BasicEntry KEY_VALUE_GENERIC_TYPE result = new BasicEntryKV_BRACES(entry.key, entry.value);
+ m.removeNode(entry);
+ return result;
+ }
+
+ @Override
+ public KEY_TYPE lowerKey(KEY_TYPE e) {
+ if(tooHigh(e)) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? getDefaultMinValue() : entry.key;
+ }
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findLowerNode(e);
+ return entry == null || tooHigh(entry.key) ? getDefaultMaxValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE floorKey(KEY_TYPE e) {
+ if(tooHigh(e)) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? getDefaultMinValue() : entry.key;
+ }
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findFloorNode(e);
+ return entry == null || tooHigh(entry.key) ? getDefaultMaxValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE ceilingKey(KEY_TYPE e) {
+ if(tooLow(e)) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? getDefaultMaxValue() : entry.key;
+ }
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findCeilingNode(e);
+ return entry == null || tooLow(entry.key) ? getDefaultMinValue() : entry.key;
+ }
+
+ @Override
+ public KEY_TYPE higherKey(KEY_TYPE e) {
+ if(tooLow(e)) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? getDefaultMaxValue() : entry.key;
+ }
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findHigherNode(e);
+ return entry == null || tooLow(entry.key) ? getDefaultMinValue() : entry.key;
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(KEY_TYPE e) {
+ if(tooHigh(e)) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findLowerNode(e);
+ return entry == null || tooHigh(entry.key) ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(KEY_TYPE e) {
+ if(tooHigh(e)) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findHighest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findFloorNode(e);
+ return entry == null || tooHigh(entry.key) ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(KEY_TYPE e) {
+ if(tooLow(e)) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findCeilingNode(e);
+ return entry == null || tooLow(entry.key) ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(KEY_TYPE e) {
+ if(tooLow(e)) {
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = findLowest();
+ return entry == null ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry = m.findHigherNode(e);
+ return entry == null || tooLow(entry.key) ? null : new BasicEntryKV_BRACES(entry.key, entry.value);
+ }
+
+ class SubMapEntrySet extends AbstractObjectSet implements ObjectSet {
+ @Override
+ @Deprecated
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) return NavigableSubMap.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
+ return NavigableSubMap.this.containsKey(((Map.Entry, ?>)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return NavigableSubMap.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return NavigableSubMap.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+ @Override
+ public ObjectIterator iterator() { return entryIterator(); }
+ @Override
+ public int size() { return NavigableSubMap.this.size(); }
+ @Override
+ public void clear() { NavigableSubMap.this.clear(); }
+ }
+
+ final class SubMapValues extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+ @Override
+ public boolean add(VALUE_TYPE o) { throw new UnsupportedOperationException(); }
+
+#if VALUE_OBJECT
+ @Override
+ public boolean contains(Object e) {
+ return containsValue(e);
+ }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) {
+ return containsValue(e);
+ }
+
+#endif
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() { return valueIterator(); }
+
+ @Override
+ public int size() {
+ return NavigableSubMap.this.size();
+ }
+
+ @Override
+ public void clear() {
+ NavigableSubMap.this.clear();
+ }
+ }
+
+ final class SubMapEntrySetIterator extends SubMapEntryIterator implements ObjectListIterator {
+ public SubMapEntrySetIterator(boolean descending) {
+ super(descending);
+ }
+
+ public SubMapEntrySetIterator(RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry, RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE lowerFence, RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE upperFence) {
+ super(entry, lowerFence, upperFence);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() { return nextEntry(); }
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() { return previousEntry(); }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ final class SubMapKeyIterator extends SubMapEntryIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
+ public SubMapKeyIterator(boolean descending) {
+ super(descending);
+ }
+
+ public SubMapKeyIterator(RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry, RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE lowerFence, RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE upperFence) {
+ super(entry, lowerFence, upperFence);
+ }
+
+ @Override
+ public KEY_TYPE NEXT() { return nextEntry().key; }
+ @Override
+ public KEY_TYPE PREVIOUS() { return previousEntry().key; }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ final class SubMapValueIterator extends SubMapEntryIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
+ public SubMapValueIterator(boolean descending) {
+ super(descending);
+ }
+
+ public SubMapValueIterator(RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry, RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE lowerFence, RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE upperFence) {
+ super(entry, lowerFence, upperFence);
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_NEXT() { return nextEntry().value; }
+ @Override
+ public VALUE_TYPE VALUE_PREVIOUS() { return previousEntry().value; }
+
+ @Override
+ public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ abstract class SubMapEntryIterator {
+ CLASS_TYPE lowerFence;
+ CLASS_TYPE upperFence;
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE next;
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE previous;
+ RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE current;
+ int index = 0;
+
+ public SubMapEntryIterator(boolean descending) {
+ this(descending ? findHighest() : findLowest(), fromStart ? null : findLowest(), toEnd ? null : findHighest());
+ }
+
+ public SubMapEntryIterator(RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE entry, RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE lowerFence, RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE upperFence) {
+ next = entry;
+ previous = entry.previous();
+ this.lowerFence = lowerFence != null ? KEY_TO_OBJ(lowerFence.key) : null;
+ this.upperFence = upperFence != null ? KEY_TO_OBJ(upperFence.key) : null;
+ }
+
+ public boolean hasNext() {
+ return next != null && (upperFence == null || KEY_EQUALS(next.key, OBJ_TO_KEY(upperFence)));
+ }
+
+ public boolean hasPrevious() {
+ return previous != null && (lowerFence == null || KEY_EQUALS(next.key, OBJ_TO_KEY(lowerFence)));
+ }
+
+ public int nextIndex() {
+ return index;
+ }
+
+ public int previousIndex() {
+ return index - 1;
+ }
+
+ protected void updateNext() {
+ next = current.next();
+ }
+
+ protected void updatePrevious() {
+ previous = current.previous();
+ }
+
+ public RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ current = previous = next;
+ updateNext();
+ index++;
+ return current;
+ }
+
+ public RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE previousEntry() {
+ if(!hasPrevious()) throw new NoSuchElementException();
+ current = next = previous;
+ updatePrevious();
+ index--;
+ return current;
+ }
+
+ public void remove() {
+ if(current == null) throw new IllegalStateException();
+ if(current == previous) index--;
+ updateNext();
+ updatePrevious();
+ if(current.needsSuccessor()) next = current;
+ m.removeNode(current);
+ current = null;
+ }
+ }
+ }
+
+ private class EntrySet extends AbstractObjectSet {
+
+ @Override
+ public ObjectIterator iterator() {
+ return new EntryIterator(false);
+ }
+
+ @Override
+ @Deprecated
+ public boolean contains(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) return RB_TREE_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
+ return RB_TREE_MAP.this.containsKey(((Map.Entry, ?>)o).getKey());
+ }
+ return false;
+ }
+
+ @Override
+ @Deprecated
+ public boolean remove(Object o) {
+ if(o instanceof Map.Entry) {
+ if(o instanceof MAP.Entry) {
+ MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
+ return RB_TREE_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
+ }
+ Map.Entry, ?> entry = (Map.Entry, ?>)o;
+ return RB_TREE_MAP.this.remove(entry.getKey(), entry.getValue());
+ }
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return RB_TREE_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ RB_TREE_MAP.this.clear();
+ }
+ }
+
+ static final class KeySet KEY_VALUE_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE {
+ NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE m;
+
+ KeySet(NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE m) {
+ this.m = m;
+ }
+
+#if !TYPE_OBJECT
+ @Override
+ public void setDefaultMaxValue(KEY_TYPE e) { m.setDefaultMaxValue(e); }
+ @Override
+ public KEY_TYPE getDefaultMaxValue() { return m.getDefaultMaxValue(); }
+ @Override
+ public void setDefaultMinValue(KEY_TYPE e) { m.setDefaultMinValue(e); }
+ @Override
+ public KEY_TYPE getDefaultMinValue() { return m.getDefaultMinValue(); }
+#endif
+ @Override
+ public boolean add(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public boolean moveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator() { return m.comparator(); }
+ @Override
+ public KEY_TYPE lower(KEY_TYPE e) { return m.lowerKey(e); }
+ @Override
+ public KEY_TYPE floor(KEY_TYPE e) { return m.floorKey(e); }
+ @Override
+ public KEY_TYPE ceiling(KEY_TYPE e) { return m.ceilingKey(e); }
+ @Override
+ public KEY_TYPE higher(KEY_TYPE e) { return m.higherKey(e); }
+ @Override
+ public KEY_TYPE FIRST_KEY() { return m.FIRST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE POLL_FIRST_KEY() { return m.POLL_FIRST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE LAST_KEY() { return m.LAST_ENTRY_KEY(); }
+ @Override
+ public KEY_TYPE POLL_LAST_KEY() { return m.POLL_LAST_ENTRY_KEY(); }
+#if TYPE_OBJECT
+ @Override
+ public boolean remove(Object o) {
+ int oldSize = m.size();
+ m.remove(o);
+ return oldSize != m.size();
+ }
+
+#else
+ @Override
+ public boolean remove(KEY_TYPE o) {
+ int oldSize = m.size();
+ m.remove(o);
+ return oldSize != m.size();
+ }
+
+#endif
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) {
+ return new KeySetKV_BRACES(m.subMap(fromElement, fromInclusive, toElement, toInclusive));
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive) {
+ return new KeySetKV_BRACES(m.headMap(toElement, inclusive));
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) {
+ return new KeySetKV_BRACES(m.tailMap(fromElement, inclusive));
+ }
+
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() {
+ return new KeySetKV_BRACES(m.descendingMap());
+ }
+
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
+ if(m instanceof RB_TREE_MAP) return ((RB_TREE_MAP KEY_VALUE_GENERIC_TYPE)m).keyIterator(false);
+ return ((NavigableSubMap KEY_VALUE_GENERIC_TYPE)m).keyIterator(false);
+ }
+
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
+ if(m instanceof RB_TREE_MAP) return ((RB_TREE_MAP KEY_VALUE_GENERIC_TYPE)m).keyIterator(fromElement);
+ return ((NavigableSubMap KEY_VALUE_GENERIC_TYPE)m).keyIterator(fromElement);
+ }
+
+ @Override
+ public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() {
+ if(m instanceof RB_TREE_MAP) return ((RB_TREE_MAP KEY_VALUE_GENERIC_TYPE)m).keyIterator(true);
+ return ((NavigableSubMap KEY_VALUE_GENERIC_TYPE)m).keyIterator(true);
+ }
+
+ @Override
+ public int size() {
+ return m.size();
+ }
+
+ @Override
+ public void clear() {
+ m.clear();
+ }
+ }
+
+ final class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
+
+ @Override
+ public boolean add(VALUE_TYPE o) { throw new UnsupportedOperationException(); }
+
+#if VALUE_OBJECT
+ @Override
+ public boolean contains(Object e) {
+ return containsValue(e);
+ }
+
+#else
+ @Override
+ public boolean contains(VALUE_TYPE e) {
+ return containsValue(e);
+ }
+
+#endif
+ @Override
+ public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() { return new ValueIterator(false); }
+
+ @Override
+ public int size() {
+ return RB_TREE_MAP.this.size();
+ }
+
+ @Override
+ public void clear() {
+ RB_TREE_MAP.this.clear();
+ }
+ }
+
+ final class EntryIterator extends MapEntryIterator implements ObjectListIterator {
+
+ public EntryIterator(boolean descending) {
+ super(descending);
+ }
+
+ public EntryIterator(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ super(entry);
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
+ return nextEntry();
+ }
+
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
+ return previousEntry();
+ }
+
+ @Override
+ public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ final class KeyIterator extends MapEntryIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
+
+ public KeyIterator(boolean descending) {
+ super(descending);
+ }
+
+ public KeyIterator(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ super(entry);
+ }
+
+ @Override
+ public KEY_TYPE PREVIOUS() { return previousEntry().key; }
+ @Override
+ public KEY_TYPE NEXT() { return nextEntry().key; }
+
+ @Override
+ public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ @Override
+ public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ final class ValueIterator extends MapEntryIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
+
+ public ValueIterator(boolean descending) {
+ super(descending);
+ }
+
+ public ValueIterator(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ super(entry);
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_PREVIOUS() {
+ return previousEntry().value;
+ }
+
+ @Override
+ public VALUE_TYPE VALUE_NEXT() {
+ return nextEntry().value;
+ }
+
+ @Override
+ public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+
+ @Override
+ public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
+ }
+
+ abstract class MapEntryIterator {
+ Entry KEY_VALUE_GENERIC_TYPE next;
+ Entry KEY_VALUE_GENERIC_TYPE previous;
+ Entry KEY_VALUE_GENERIC_TYPE current;
+ int index = 0;
+
+ public MapEntryIterator(boolean descending) {
+ if(descending) previous = last;
+ else next = first;
+ }
+
+ public MapEntryIterator(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ next = entry;
+ previous = entry.previous();
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public boolean hasPrevious() {
+ return previous != null;
+ }
+
+ public int nextIndex() {
+ return index;
+ }
+
+ public int previousIndex() {
+ return index - 1;
+ }
+
+ protected void updateNext() {
+ next = current.next();
+ }
+
+ protected void updatePrevious() {
+ previous = current.previous();
+ }
+
+ public Entry KEY_VALUE_GENERIC_TYPE nextEntry() {
+ if(!hasNext()) throw new NoSuchElementException();
+ current = previous = next;
+ updateNext();
+ index++;
+ return current;
+ }
+
+ public Entry KEY_VALUE_GENERIC_TYPE previousEntry() {
+ if(!hasPrevious()) throw new NoSuchElementException();
+ current = next = previous;
+ updatePrevious();
+ index--;
+ return current;
+ }
+
+ public void remove() {
+ if(current == null) throw new IllegalStateException();
+ if(current == previous) index--;
+ updateNext();
+ updatePrevious();
+ if(current.needsSuccessor()) next = current;
+ removeNode(current);
+ current = null;
+ }
+ }
+
+ private static final class Entry KEY_VALUE_GENERIC_TYPE implements MAP.Entry KEY_VALUE_GENERIC_TYPE
+ {
+ static final int BLACK = 1;
+
+ KEY_TYPE key;
+ VALUE_TYPE value;
+ int state;
+ Entry KEY_VALUE_GENERIC_TYPE parent;
+ Entry KEY_VALUE_GENERIC_TYPE left;
+ Entry KEY_VALUE_GENERIC_TYPE right;
+
+ Entry(KEY_TYPE key, VALUE_TYPE value, Entry KEY_VALUE_GENERIC_TYPE parent) {
+ this.key = key;
+ this.value = value;
+ this.parent = parent;
+ }
+
+ @Override
+ public KEY_TYPE ENTRY_KEY() {
+ return key;
+ }
+
+ @Override
+ public VALUE_TYPE ENTRY_VALUE() {
+ return value;
+ }
+
+ @Override
+ public VALUE_TYPE setValue(VALUE_TYPE value) {
+ VALUE_TYPE oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+#if VALUE_PRIMITIVES
+ VALUE_TYPE addTo(VALUE_TYPE value) {
+ VALUE_TYPE oldValue = this.value;
+ this.value += value;
+ return oldValue;
+ }
+
+#endif
+ boolean isBlack() {
+ return (state & BLACK) != 0;
+ }
+
+ void setBlack(boolean value) {
+ if(value) state |= BLACK;
+ else state &= ~BLACK;
+ }
+
+ boolean needsSuccessor() { return left != null && right != null; }
+
+ boolean replace(Entry KEY_VALUE_GENERIC_TYPE entry) {
+ if(entry != null) entry.parent = parent;
+ if(parent != null) {
+ if(parent.left == this) parent.left = entry;
+ else parent.right = entry;
+ }
+ return parent == null;
+ }
+
+ Entry KEY_VALUE_GENERIC_TYPE next() {
+ if(right != null) {
+ Entry KEY_VALUE_GENERIC_TYPE parent = right;
+ while(parent.left != null) parent = parent.left;
+ return parent;
+ }
+ Entry KEY_VALUE_GENERIC_TYPE parent = this.parent;
+ Entry KEY_VALUE_GENERIC_TYPE control = this;
+ while(parent != null && control == parent.right) {
+ control = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+
+ Entry KEY_VALUE_GENERIC_TYPE previous() {
+ if(left != null) {
+ Entry KEY_VALUE_GENERIC_TYPE parent = left;
+ while(parent.right != null) parent = parent.right;
+ return parent;
+ }
+ Entry KEY_VALUE_GENERIC_TYPE parent = this.parent;
+ Entry KEY_VALUE_GENERIC_TYPE control = this;
+ while(parent != null && control == parent.left) {
+ control = parent;
+ parent = parent.parent;
+ }
+ return parent;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/interfaces/Map.template b/src/main/resources/speiger/assets/collections/templates/maps/interfaces/Map.template
index c4cb1c2..20236fd 100644
--- a/src/main/resources/speiger/assets/collections/templates/maps/interfaces/Map.template
+++ b/src/main/resources/speiger/assets/collections/templates/maps/interfaces/Map.template
@@ -30,7 +30,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map
+{
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap();
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE navigableKeySet();
+ @Override
+ public NAVIGABLE_SET KEY_GENERIC_TYPE descendingKeySet();
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE firstEntry();
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lastEntry();
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirstEntry();
+ @Override
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLastEntry();
+
+#if !TYPE_OBJECT
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive);
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive);
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive);
+
+ @Override
+ public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey) { return subMap(fromKey, true, toKey, false); }
+ @Override
+ public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey) { return headMap(toKey, false); }
+ @Override
+ public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey) { return tailMap(fromKey, true); }
+
+ public void setDefaultMaxValue(KEY_TYPE e);
+ public KEY_TYPE getDefaultMaxValue();
+
+ public void setDefaultMinValue(KEY_TYPE e);
+ public KEY_TYPE getDefaultMinValue();
+
+ public KEY_TYPE lowerKey(KEY_TYPE key);
+ public KEY_TYPE higherKey(KEY_TYPE key);
+ public KEY_TYPE floorKey(KEY_TYPE key);
+ public KEY_TYPE ceilingKey(KEY_TYPE key);
+
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(KEY_TYPE key);
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(KEY_TYPE key);
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(KEY_TYPE key);
+ public MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(KEY_TYPE key);
+
+ @Override
+ public default CLASS_TYPE lowerKey(CLASS_TYPE key) { return KEY_TO_OBJ(lowerKey(OBJ_TO_KEY(key)));}
+ @Override
+ public default CLASS_TYPE floorKey(CLASS_TYPE key) { return KEY_TO_OBJ(floorKey(OBJ_TO_KEY(key)));}
+ @Override
+ public default CLASS_TYPE ceilingKey(CLASS_TYPE key) { return KEY_TO_OBJ(ceilingKey(OBJ_TO_KEY(key)));}
+ @Override
+ public default CLASS_TYPE higherKey(CLASS_TYPE key) { return KEY_TO_OBJ(higherKey(OBJ_TO_KEY(key)));}
+
+ @Override
+ default MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(CLASS_TYPE key) { return lowerEntry(OBJ_TO_KEY(key)); }
+ @Override
+ default MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(CLASS_TYPE key) { return floorEntry(OBJ_TO_KEY(key)); }
+ @Override
+ default MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(CLASS_TYPE key) { return ceilingEntry(OBJ_TO_KEY(key)); }
+ @Override
+ default MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(CLASS_TYPE key) { return higherEntry(OBJ_TO_KEY(key)); }
+
+ @Override
+ default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, boolean fromInclusive, CLASS_TYPE toKey, boolean toInclusive) { return subMap(OBJ_TO_KEY(fromKey), fromInclusive, OBJ_TO_KEY(toKey), toInclusive); }
+ @Override
+ default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey, boolean inclusive) { return headMap(OBJ_TO_KEY(toKey), inclusive); }
+ @Override
+ default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey, boolean inclusive) { return tailMap(OBJ_TO_KEY(fromKey), inclusive); }
+ @Override
+ default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, CLASS_TYPE toKey) { return subMap(OBJ_TO_KEY(fromKey), true, OBJ_TO_KEY(toKey), false); }
+ @Override
+ default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey) { return headMap(OBJ_TO_KEY(toKey), false); }
+ @Override
+ default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey) { return tailMap(OBJ_TO_KEY(fromKey), true); }
+#else
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, boolean fromInclusive, CLASS_TYPE toKey, boolean toInclusive);
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey, boolean inclusive);
+ @Override
+ public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey, boolean inclusive);
+ @Override
+ public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, CLASS_TYPE toKey) { return subMap(fromKey, true, toKey, false); }
+ @Override
+ public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey) { return headMap(toKey, false); }
+ @Override
+ public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey) { return tailMap(fromKey, true); }
+#endif
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/maps/interfaces/SortedMap.template b/src/main/resources/speiger/assets/collections/templates/maps/interfaces/SortedMap.template
new file mode 100644
index 0000000..e5528a2
--- /dev/null
+++ b/src/main/resources/speiger/assets/collections/templates/maps/interfaces/SortedMap.template
@@ -0,0 +1,73 @@
+package speiger.src.collections.PACKAGE.maps.interfaces;
+
+#if TYPE_OBJECT
+import java.util.Comparator;
+#endif
+import java.util.SortedMap;
+
+import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
+#if !TYPE_OBJECT
+import speiger.src.collections.PACKAGE.functions.COMPARATOR;
+#endif
+import speiger.src.collections.PACKAGE.sets.SET;
+import speiger.src.collections.objects.sets.ObjectSortedSet;
+import speiger.src.collections.objects.collections.ObjectBidirectionalIterator;
+
+public interface SORTED_MAP KEY_VALUE_GENERIC_TYPE extends SortedMap, MAP KEY_VALUE_GENERIC_TYPE
+{
+ public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value);
+ public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value);
+
+ public boolean moveToFirst(KEY_TYPE key);
+ public boolean moveToLast(KEY_TYPE key);
+
+ public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key);
+ public VALUE_TYPE getAndMoveToLast(KEY_TYPE key);
+
+ @Override
+ public COMPARATOR KEY_GENERIC_TYPE comparator();
+
+ @Override
+ public SET KEY_GENERIC_TYPE keySet();
+ @Override
+ public VALUE_COLLECTION VALUE_GENERIC_TYPE values();
+
+#if !TYPE_OBJECT
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey);
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey);
+ public SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey);
+
+ public KEY_TYPE FIRST_ENTRY_KEY();
+ public KEY_TYPE POLL_FIRST_ENTRY_KEY();
+ public KEY_TYPE LAST_ENTRY_KEY();
+ public KEY_TYPE POLL_LAST_ENTRY_KEY();
+
+ public VALUE_TYPE FIRST_ENTRY_VALUE();
+ public VALUE_TYPE LAST_ENTRY_VALUE();
+
+ public default CLASS_TYPE firstKey() { return KEY_TO_OBJ(FIRST_ENTRY_KEY()); }
+ public default CLASS_TYPE lastKey() { return KEY_TO_OBJ(LAST_ENTRY_KEY()); }
+
+ @Override
+ @Deprecated
+ public default SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, CLASS_TYPE toKey) { return subMap(OBJ_TO_KEY(fromKey), OBJ_TO_KEY(toKey)); }
+ @Override
+ @Deprecated
+ public default SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey) { return headMap(OBJ_TO_KEY(toKey)); }
+ @Override
+ @Deprecated
+ public default SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey) { return tailMap(OBJ_TO_KEY(fromKey)); }
+#else
+ public KEY_TYPE POLL_FIRST_ENTRY_KEY();
+ public KEY_TYPE POLL_LAST_ENTRY_KEY();
+
+ public VALUE_TYPE FIRST_ENTRY_VALUE();
+ public VALUE_TYPE LAST_ENTRY_VALUE();
+#endif
+
+ interface FastSortedSet KEY_VALUE_GENERIC_TYPE extends MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE, ObjectSortedSet {
+ @Override
+ public ObjectBidirectionalIterator fastIterator();
+ public ObjectBidirectionalIterator fastIterator(KEY_TYPE fromElement);
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/speiger/assets/collections/templates/sets/ArraySet.template b/src/main/resources/speiger/assets/collections/templates/sets/ArraySet.template
index 3d7f408..82fe2ef 100644
--- a/src/main/resources/speiger/assets/collections/templates/sets/ArraySet.template
+++ b/src/main/resources/speiger/assets/collections/templates/sets/ArraySet.template
@@ -4,15 +4,20 @@ import java.util.Arrays;
import java.util.Collection;
#if TYPE_OBJECT
import java.util.Comparator;
+import java.util.function.Consumer;
#endif
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
+#if PRIMITIVES
+import java.util.function.JAVA_PREDICATE;
+#endif
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
import speiger.src.collections.PACKAGE.collections.COLLECTION;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
+import speiger.src.collections.PACKAGE.functions.CONSUMER;
#endif
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
import speiger.src.collections.PACKAGE.utils.ARRAYS;
@@ -191,9 +196,9 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
public KEY_TYPE POLL_FIRST_KEY() {
if(size == 0) throw new NoSuchElementException();
KEY_TYPE result = data[0];
- System.arraycopy(data, 1, data, 0, size - 1);
+ System.arraycopy(data, 1, data, 0, --size);
#if TYPE_OBJECT
- data[size-1] = EMPTY_KEY_VALUE;
+ data[size] = EMPTY_KEY_VALUE;
#endif
return result;
}
@@ -210,7 +215,36 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
return data[size];
#endif
}
+#if PRIMITIVES
+ @Override
+ public boolean remIf(JAVA_PREDICATE KEY_GENERIC_TYPE filter) {
+ Objects.requireNonNull(filter);
+ boolean modified = false;
+ int j = 0;
+ for(int i = 0;i=0;i--)
diff --git a/src/main/resources/speiger/assets/collections/templates/sets/LinkedOpenCustomHashSet.template b/src/main/resources/speiger/assets/collections/templates/sets/LinkedOpenCustomHashSet.template
index afecbf1..22d4c89 100644
--- a/src/main/resources/speiger/assets/collections/templates/sets/LinkedOpenCustomHashSet.template
+++ b/src/main/resources/speiger/assets/collections/templates/sets/LinkedOpenCustomHashSet.template
@@ -174,7 +174,6 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
}
pos = ++pos & mask;
}
- keys[pos] = o;
}
return false;
}
@@ -197,7 +196,6 @@ public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY
}
pos = ++pos & mask;
}
- keys[pos] = o;
}
return false;
}
diff --git a/src/main/resources/speiger/assets/collections/templates/sets/LinkedOpenHashSet.template b/src/main/resources/speiger/assets/collections/templates/sets/LinkedOpenHashSet.template
index 141b836..2470339 100644
--- a/src/main/resources/speiger/assets/collections/templates/sets/LinkedOpenHashSet.template
+++ b/src/main/resources/speiger/assets/collections/templates/sets/LinkedOpenHashSet.template
@@ -176,7 +176,6 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
}
pos = ++pos & mask;
}
- keys[pos] = o;
}
return false;
}
@@ -199,7 +198,6 @@ public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE
}
pos = ++pos & mask;
}
- keys[pos] = o;
}
return false;
}
diff --git a/src/main/resources/speiger/assets/collections/templates/sets/RBTreeSet.template b/src/main/resources/speiger/assets/collections/templates/sets/RBTreeSet.template
index 0830296..b972a1e 100644
--- a/src/main/resources/speiger/assets/collections/templates/sets/RBTreeSet.template
+++ b/src/main/resources/speiger/assets/collections/templates/sets/RBTreeSet.template
@@ -701,13 +701,13 @@ public class RB_TREE_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE
#if !TYPE_OBJECT
@Override
- public void setDefaultMaxValue(KEY_TYPE value) { throw new UnsupportedOperationException(); }
+ public void setDefaultMaxValue(KEY_TYPE value) { set.setDefaultMaxValue(value); }
@Override
public KEY_TYPE getDefaultMaxValue() { return set.getDefaultMaxValue(); }
@Override
- public void setDefaultMinValue(KEY_TYPE value) { throw new UnsupportedOperationException(); }
+ public void setDefaultMinValue(KEY_TYPE value) { set.setDefaultMinValue(value); }
@Override
public KEY_TYPE getDefaultMinValue() { return set.getDefaultMinValue(); }
diff --git a/src/main/resources/speiger/assets/collections/templates/sets/SortedSet.template b/src/main/resources/speiger/assets/collections/templates/sets/SortedSet.template
index ce4f4d1..845e2ae 100644
--- a/src/main/resources/speiger/assets/collections/templates/sets/SortedSet.template
+++ b/src/main/resources/speiger/assets/collections/templates/sets/SortedSet.template
@@ -12,11 +12,9 @@ import speiger.src.collections.PACKAGE.functions.COMPARATOR;
public interface SORTED_SET KEY_GENERIC_TYPE extends SET KEY_GENERIC_TYPE, SortedSet
{
public boolean addAndMoveToFirst(KEY_TYPE o);
-
public boolean addAndMoveToLast(KEY_TYPE o);
public boolean moveToFirst(KEY_TYPE o);
-
public boolean moveToLast(KEY_TYPE o);
@Override
@@ -24,32 +22,24 @@ public interface SORTED_SET KEY_GENERIC_TYPE extends SET KEY_GENERIC_TYPE, Sorte
@Override
public BI_ITERATOR KEY_GENERIC_TYPE iterator();
-
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement);
#if !TYPE_OBJECT
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement);
-
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement);
-
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement);
public KEY_TYPE FIRST_KEY();
-
public KEY_TYPE POLL_FIRST_KEY();
-
public KEY_TYPE LAST_KEY();
-
public KEY_TYPE POLL_LAST_KEY();
@Override
@Deprecated
public default SORTED_SET KEY_GENERIC_TYPE subSet(CLASS_TYPE fromElement, CLASS_TYPE toElement) { return subSet(OBJ_TO_KEY(fromElement), OBJ_TO_KEY(toElement)); }
-
@Override
@Deprecated
public default SORTED_SET KEY_GENERIC_TYPE headSet(CLASS_TYPE toElement) { return headSet(OBJ_TO_KEY(toElement)); }
-
@Override
@Deprecated
public default SORTED_SET KEY_GENERIC_TYPE tailSet(CLASS_TYPE fromElement) { return tailSet(OBJ_TO_KEY(fromElement)); }
@@ -57,21 +47,17 @@ public interface SORTED_SET KEY_GENERIC_TYPE extends SET KEY_GENERIC_TYPE, Sorte
@Override
@Deprecated
public default CLASS_TYPE first() { return KEY_TO_OBJ(FIRST_KEY()); }
-
@Override
@Deprecated
default CLASS_TYPE last() { return KEY_TO_OBJ(LAST_KEY()); }
#else
public CLASS_TYPE pollFirst();
-
public CLASS_TYPE pollLast();
@Override
public SORTED_SET KEY_GENERIC_TYPE subSet(CLASS_TYPE fromElement, CLASS_TYPE toElement);
-
@Override
public SORTED_SET KEY_GENERIC_TYPE headSet(CLASS_TYPE toElement);
-
@Override
public SORTED_SET KEY_GENERIC_TYPE tailSet(CLASS_TYPE fromElement);
#endif
diff --git a/src/main/resources/speiger/assets/collections/templates/utils/Iterators.template b/src/main/resources/speiger/assets/collections/templates/utils/Iterators.template
index 964e952..ffe0965 100644
--- a/src/main/resources/speiger/assets/collections/templates/utils/Iterators.template
+++ b/src/main/resources/speiger/assets/collections/templates/utils/Iterators.template
@@ -24,6 +24,44 @@ public class ITERATORS
#endif
}
+ public static GENERIC_KEY_BRACES BI_ITERATOR KEY_GENERIC_TYPE invert(BI_ITERATOR KEY_GENERIC_TYPE it) {
+ return new BI_ITERATOR KEY_GENERIC_TYPE() {
+ @Override
+ public KEY_TYPE NEXT() { return it.PREVIOUS(); }
+ @Override
+ public boolean hasNext() { return it.hasPrevious(); }
+ @Override
+ public boolean hasPrevious() { return it.hasNext(); }
+ @Override
+ public KEY_TYPE PREVIOUS() { return it.NEXT(); }
+ @Override
+ public void remove() { it.remove(); }
+ };
+ }
+
+ public static GENERIC_KEY_BRACES LIST_ITERATOR KEY_GENERIC_TYPE invert(LIST_ITERATOR KEY_GENERIC_TYPE it) {
+ return new LIST_ITERATOR KEY_GENERIC_TYPE() {
+ @Override
+ public KEY_TYPE NEXT() { return it.PREVIOUS(); }
+ @Override
+ public boolean hasNext() { return it.hasPrevious(); }
+ @Override
+ public boolean hasPrevious() { return it.hasNext(); }
+ @Override
+ public KEY_TYPE PREVIOUS() { return it.NEXT(); }
+ @Override
+ public void remove() { it.remove(); }
+ @Override
+ public int nextIndex() { return it.previousIndex(); }
+ @Override
+ public int previousIndex() { return it.nextIndex(); }
+ @Override
+ public void set(KEY_TYPE e) { it.set(e); }
+ @Override
+ public void add(KEY_TYPE e) { it.add(e); }
+ };
+ }
+
/**
* Returns a Immutable Iterator instance based on the instance given.
* @param l that should be made immutable/unmodifyable