diff --git a/collections-fastutil/src/main/java-templates/space/vectrix/sync/collections/fastutil/{{key}}2ObjectBucketSyncMap.java.peb b/collections-fastutil/src/main/java-templates/space/vectrix/sync/collections/fastutil/{{key}}2ObjectBucketSyncMap.java.peb index 840b609..d761e37 100644 --- a/collections-fastutil/src/main/java-templates/space/vectrix/sync/collections/fastutil/{{key}}2ObjectBucketSyncMap.java.peb +++ b/collections-fastutil/src/main/java-templates/space/vectrix/sync/collections/fastutil/{{key}}2ObjectBucketSyncMap.java.peb @@ -372,6 +372,13 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa * @since 1.0.0 */ public {{ key }}2ObjectBucketSyncMap(final SpreadFunction spreadFunction, final int initialCapacity, final float loadFactor) { + requireNonNull(spreadFunction, "spreadFunction"); + + if(initialCapacity < 0) throw new IllegalArgumentException("Initial capacity must be non-negative"); + if(loadFactor <= 0.0F || !Float.isFinite(loadFactor)) { + throw new IllegalArgumentException("Load factor must be positive and finite"); + } + final int capacity = initialCapacity >= {{ key }}2ObjectBucketSyncMap.MAXIMUM_CAPACITY ? {{ key }}2ObjectBucketSyncMap.MAXIMUM_CAPACITY : {{ key }}2ObjectBucketSyncMap.tableSizeFor(initialCapacity); @@ -510,16 +517,14 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa @Override @Deprecated @SuppressWarnings("deprecation") - public @Nullable V getOrDefault(final Object key, final V defaultValue) { + public @Nullable V getOrDefault(final Object key, final @Nullable V defaultValue) { requireNonNull(key, "key"); - return super.getOrDefault(key, defaultValue); + return this.getOrDefault(({{ keyPrimitive }}) key, defaultValue); } @Override - public V getOrDefault(final {{ keyPrimitive }} key, final V defaultValue) { - requireNonNull(defaultValue, "defaultValue"); - + public @Nullable V getOrDefault(final {{ keyPrimitive }} key, final @Nullable V defaultValue) { Node@UnknownNullability [] table = this.immutableTable; int length = table.length; Node node; @@ -897,10 +902,12 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa } } - if(!this.amended || (mutable = this.mutableTable) == null) return null; - final int index; - if((node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) != null) { + if(!this.amended || (mutable == null && (mutable = this.mutableTable) == null) || (node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) == null) { + return null; + } else if(node.hash == {{ key }}2ObjectBucketSyncMap.NODE_MOVED) { + mutable = this.forward((ForwardingNode) node); + } else { synchronized(node) { if({{ key }}2ObjectBucketSyncMap.getNodePlain(mutable, index) == node) { for(Node previousNode = null; ; ) { @@ -1339,7 +1346,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa Object previous; Node[] immutable; - Node@org.jetbrains.annotations.Nullable [] mutable; + Node@org.jetbrains.annotations.Nullable [] mutable = null; int length; Node node; @@ -1376,10 +1383,12 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa } } - if(!this.amended || (mutable = this.mutableTable) == null) return null; - final int index; - if((node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) != null) { + if(!this.amended || (mutable == null && (mutable = this.mutableTable) == null) || (node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) == null) { + return null; + } else if(node.hash == {{ key }}2ObjectBucketSyncMap.NODE_MOVED) { + mutable = this.forward((ForwardingNode) node); + } else { synchronized(node) { if({{ key }}2ObjectBucketSyncMap.getNodePlain(mutable, index) == node) { for(Node previousNode = null; ; ) { @@ -1433,7 +1442,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa requireNonNull(value, "value"); Node[] immutable; - Node@org.jetbrains.annotations.Nullable [] mutable; + Node@org.jetbrains.annotations.Nullable [] mutable = null; int length; Node node; @@ -1471,10 +1480,12 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa } } - if(!this.amended || (mutable = this.mutableTable) == null) return false; - final int index; - if((node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) != null) { + if(!this.amended || (mutable == null && (mutable = this.mutableTable) == null) || (node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) == null) { + return false; + } else if(node.hash == {{ key }}2ObjectBucketSyncMap.NODE_MOVED) { + mutable = this.forward((ForwardingNode) node); + } else { synchronized(node) { if({{ key }}2ObjectBucketSyncMap.getNodePlain(mutable, index) == node) { for(Node previousNode = null; ; ) { @@ -1532,7 +1543,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa Object previous; Node[] immutable; - Node@org.jetbrains.annotations.Nullable [] mutable; + Node@org.jetbrains.annotations.Nullable [] mutable = null; int length; Node node; @@ -1569,10 +1580,12 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa } } - if(!this.amended || (mutable = this.mutableTable) == null) return null; - final int index; - if((node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) != null) { + if(!this.amended || (mutable == null && (mutable = this.mutableTable) == null) || (node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) == null) { + return null; + } else if(node.hash == {{ key }}2ObjectBucketSyncMap.NODE_MOVED) { + mutable = this.forward((ForwardingNode) node); + } else { synchronized(node) { if({{ key }}2ObjectBucketSyncMap.getNodePlain(mutable, index) == node) { for(; ; ) { @@ -1620,7 +1633,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa Object previous; Node[] immutable; - Node@org.jetbrains.annotations.Nullable [] mutable; + Node@org.jetbrains.annotations.Nullable [] mutable = null; int length; Node node; @@ -1658,10 +1671,12 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa } } - if(!this.amended || (mutable = this.mutableTable) == null) return false; - final int index; - if((node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) != null) { + if(!this.amended || (mutable == null && (mutable = this.mutableTable) == null) || (node = {{ key }}2ObjectBucketSyncMap.getNode(mutable, index = (mutable.length - 1) & hash)) == null) { + return false; + } else if(node.hash == {{ key }}2ObjectBucketSyncMap.NODE_MOVED) { + mutable = this.forward((ForwardingNode) node); + } else { synchronized(node) { if({{ key }}2ObjectBucketSyncMap.getNodePlain(mutable, index) == node) { for(; ; ) { @@ -1733,7 +1748,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa final ObjectReference reference = node.referencePlain(); Object current = reference.get(); for(; ; ) { - if(current == null || current == {{ key }}2ObjectBucketSyncMap.EXPUNGED) continue; + if(current == null || current == {{ key }}2ObjectBucketSyncMap.EXPUNGED) break; final Object witness = reference.compareAndExchange(current, null); if(witness != current) { @@ -1881,6 +1896,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa if(!this.amended || (source = this.mutableTable) == null || (length = source.length) <= 0 + || length >= {{ key }}2ObjectBucketSyncMap.MAXIMUM_CAPACITY || this.size.sum() < ((long) length * this.loadFactor)) return; operation = StampLock.operation(state); @@ -2451,7 +2467,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa } @SuppressWarnings("unchecked") - private V valueOr(final V defaultValue) { + private @Nullable V valueOr(final @Nullable V defaultValue) { final Object value; return ((value = ObjectReference.VALUE.getAcquire(this)) != null && value != {{ key }}2ObjectBucketSyncMap.EXPUNGED) ? (V) value : defaultValue; } @@ -2613,7 +2629,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa @Override public int hashCode() { - return Objects.hash(this.key, this.value); + return Objects.hashCode(this.key) ^ Objects.hashCode(this.value); } @Override @@ -2626,7 +2642,7 @@ public class {{ key }}2ObjectBucketSyncMap extends Abstract{{ key }}2ObjectMa @Override public String toString() { - return "SyncMap.Entry{key=" + this.key + ", value=" + this.value + "}"; + return "{{ key }}2ObjectBucketSyncMap.Entry{key=" + this.key + ", value=" + this.value + "}"; } } diff --git a/collections-fastutil/src/test/java-templates/space/vectrix/sync/collections/fastutil/{{key}}2ObjectAbstractMapTest.java.peb b/collections-fastutil/src/test/java-templates/space/vectrix/sync/collections/fastutil/{{key}}2ObjectAbstractMapTest.java.peb index 4bfa886..26e5649 100644 --- a/collections-fastutil/src/test/java-templates/space/vectrix/sync/collections/fastutil/{{key}}2ObjectAbstractMapTest.java.peb +++ b/collections-fastutil/src/test/java-templates/space/vectrix/sync/collections/fastutil/{{key}}2ObjectAbstractMapTest.java.peb @@ -140,7 +140,6 @@ public abstract class {{ key }}2ObjectAbstractMapTest { @Test public void test_getOrDefault_nullKey() { final {{ key }}2ObjectMap map = this.createMap(); - assertThrows(NullPointerException.class, () -> map.getOrDefault(this.key(3), null), "Map should throw exception when given a null default value."); assertThrows(NullPointerException.class, () -> map.getOrDefault(null, this.value(3)), "Map should throw exception when given a null key."); }