From f60a287868bca16a23f5b5064c8a62cefd8fdbb1 Mon Sep 17 00:00:00 2001 From: Speiger Date: Thu, 28 Jan 2021 20:42:29 +0100 Subject: [PATCH] Added Maps -Added: ArrayMap/(Custom/Linked/HashMap)/TreeMap(RB/AVL)/EnumMap -Reworked: Some Variables and how Types are chosen. --- .classpath | 2 +- build.gradle | 30 +- libs/Simple Code Generator-1.0.1-sources.jar | Bin 13289 -> 13474 bytes libs/Simple Code Generator-1.0.1.jar | Bin 26884 -> 27211 bytes .../src/builder/example/GlobalVariables.java | 49 +- .../src/builder/example/TestBuilder.java | 67 +- .../maps/abstracts/AbstractMap.template | 19 +- .../LinkedOpenCustomHashMap.template | 999 ++++++++++ .../customHash/OpenCustomHashMap.template | 781 ++++++++ .../maps/impl/hash/LinkedOpenHashMap.template | 1001 ++++++++++ .../maps/impl/hash/OpenHashMap.template | 776 ++++++++ .../maps/impl/misc/ArrayMap.template | 1653 ++++++++++++++++ .../templates/maps/impl/misc/EnumMap.template | 332 ++++ .../maps/impl/tree/AVLTreeMap.template | 1688 ++++++++++++++++ .../maps/impl/tree/RBTreeMap.template | 1750 +++++++++++++++++ .../templates/maps/interfaces/Map.template | 12 +- .../maps/interfaces/NavigableMap.template | 95 + .../maps/interfaces/SortedMap.template | 73 + .../templates/sets/ArraySet.template | 38 +- .../sets/LinkedOpenCustomHashSet.template | 2 - .../templates/sets/LinkedOpenHashSet.template | 2 - .../templates/sets/RBTreeSet.template | 4 +- .../templates/sets/SortedSet.template | 14 - .../templates/utils/Iterators.template | 38 + 24 files changed, 9342 insertions(+), 83 deletions(-) create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/impl/customHash/LinkedOpenCustomHashMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/impl/hash/LinkedOpenHashMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/impl/misc/ArrayMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/impl/misc/EnumMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/impl/tree/AVLTreeMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/impl/tree/RBTreeMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/interfaces/NavigableMap.template create mode 100644 src/main/resources/speiger/assets/collections/templates/maps/interfaces/SortedMap.template 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 9b3630f7054d7ed4d6385522c11a77420b23ae03..60e0673e291fd2aa542da94cb5ab23ab1ada2c21 100644 GIT binary patch delta 2565 zcmZXWcQ_l08pb2BOT)2g5QGv+Z4skNRby4{h*euvh*eaKQsYpBpwwP1PK_EdD|UOT zs9B?SX+&)~rR_cEJoh>G-sgVrU+?!l-}m49e7|kaQg3#16o{S`0AOYYkb)2m>?k45 zG#tVrZ6jzP9s~e1GXnrpgn$ctglHjdyfxbYg93Ndef&TPc=&e8l$fp;`dS>%?Igd% zi($Dk>k_8En+Rw~i&g#4(ftZi77&~wRFu+#>;9?^w+-yGz7*6ukep+g!;%Vz-Z}5$ zL}=`u4pa`KK%eI1%EYStU&yY(%zB9Ay@Rk%$ew~lsZIqk8~jJh+j;TQ8uLMTKi1T| z^n&ib$3If2;!2d?j1J57xY6OG&4V(d_4I!2+S#0$g+$nV6bF-^$fNd^?TE^m&$a4a zI{cdjX9hf|3|+CjY3E-2jr`r8JEyS*LLS(pLx;dh-7R_Jb+iIQ@7x7piF^xk&N-6Y17+&1LN8 z9B(hq%*kNUpU`q|(z9|r0g@@yJr#2pjtITc7-ux@8>4qh-ksxr5pWTNJECs8p7=#I z~ipM(`BOOi_?r(M(7>Sb_}(3Z5mEkhQz<}LagtCx=F4l3MBCMLn;D zCLFpXe=VuI)&HDNDCko1_C11!XaT*$RiJ6)Di#GvS*ee=8sZ*`so|DZT=?N>?mNPV zmm}`+51!ib_HxXO@Ym#aCfW<;>DSqZI8}t1W&JF?kjLS!bN9Fwd4vZw?F#cVab^c0 zEFeuN?_dT1fF2A0DE}SRE0R#W4GK4}%At+w0q#RVsXUXT#_~k!uM|T{Qg)bFRgUpR z4pOFh96b}jy(8&I1RuCtLeeL)_~uT;={%-wc|_a^c$Fa$=H(GY-mFNM?&h>s$2A`*dFJ4Nucm1svcR-)?Su9pFJkgvem_s{a)OL9viJ zT8yWHk7rel#x?G#Jm7Ut>y$`4RGJY(?}xhDLV`N-q`iV}pkHvePgL;?WaQ#_Mdx!x zjB<26kp(KNKkEJt^1XQKRL{llM*nZG!WGL^h6dMFTZ@D3il@FQTiVHP!E@YY+kXn{ zW9=}Ad-48XpjOZ)hUz~!Rd+nD9h@%1T9cc~yWdha#S+22)T+iP;;h$Qx@ zrxnR7$(lwOfqOvB@CQ4qUq1&KGrv_?Y0Rs<7gz&_$mUR?6>*Rgue$zdy&`LLezExm+g9^Uhv=Xj#ETi&b*kE`z(hh)6!~av2`8HJGN>PG z#4_@^G4Hh`S;F3xaVH{rRnJv%ajAUB@UDfNxoTHeN5?aaQ`9+Dg_0N`J@uhtf&+;K zil9&!LdaCkA=^ApQ!4*y{dEoteIZW%^>MtqrtfPXg-~0=fTt$?DFd8!@|3hsLEFqT2|F$_et;DiF+~NB!R;HYrQtnj(lpjbIjymraQm7%Xy??^$ES-J*S4tY@^3C8s~=h#9D#7 zx^C7nYV_@V?<|L`9(_5jUjQ~Q;iJsp>!ntU8T(=Zu^4Y#N~^hpo%-=>_+H*=s}8X1C6&xcRX2Sxh8o_3t(c7`j-->-tEb*+1D7 zUZ!mADm`X$3iy=iV7I!7be!7Tq+1vCEJ+w+l4!ZJfcMVNjn&4f zg}qaNTdpxIn(Dvx)9ok?&;P-z%WLlrA+GUWXb;5FbOu3+o{WZgmALvfwx`-qxh{X- zuC(lzTG+6v=*U@SIG^y@$zb!6kf;3zQ}u zwI<}Qgn1|0w7$bCorBFUqUeC!pntfk={h`_k^O(bitzEO2asQca8*c%fKgNjQlNx= zE?z>E1S_FcQ3fb2_K(#RyGYGr9TonU`xlLJyT$+j delta 2349 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 N9D-Hi$EyDy{tbslLi_*# diff --git a/libs/Simple Code Generator-1.0.1.jar b/libs/Simple Code Generator-1.0.1.jar index 952d60da544319ac47e4a4be1acc98be334c21a4..e6cde347d3bb097d2b3118b6c4117c15f31b2efa 100644 GIT binary patch delta 7151 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 E1JkjJ@&Et; delta 6830 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 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() ? "" : ""); - addSimpleMapper(" VALUE_SUPER_GENERIC_TYPE", valueType.isObject() ? "" : ""); + addSimpleMapper(" VALUE_SUPER_GENERIC_TYPE", valueType.isObject() ? "" : ""); addSimpleMapper(" KEY_VALUE_SUPER_GENERIC_TYPE", type.isObject() ? (valueType.isObject() ? "" : "") : (valueType.isObject() ? "" : "")); - - + 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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