More Fixes

- Fixed: containsKey & containsValue in HashMaps were deprecated for
Object Variants.
- Fixed: HashMap wasn't deleting Keys & Values references when removing
a Object
- Fixed: AVLTreeSet didn't balance properly.
- Changed: EnumMap no longer tries to access SharedSecrets since its
gone in java11
This commit is contained in:
2021-06-24 13:17:48 +02:00
parent 3c0f4acc05
commit c0fef15e64
7 changed files with 64 additions and 18 deletions
@@ -36,6 +36,7 @@ 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;
import speiger.src.collections.utils.ITrimmable;
/**
* A Type Specific HashMap that allows for custom HashControl.
@@ -43,7 +44,7 @@ import speiger.src.collections.utils.HashUtil;
* @Type(T)
* @ValueType(V)
*/
public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE
public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements ITrimmable
{
/** The Backing keys array */
protected transient KEY_TYPE[] keys;
@@ -262,7 +263,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
#endif
@Override
@Deprecated
@Primitive
public boolean containsKey(Object key) {
#if !TYPE_OBJECT
return key instanceof CLASS_TYPE && findIndex(CLASS_TO_KEY(key)) >= 0;
@@ -282,7 +283,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
#endif
@Override
@Deprecated
@ValuePrimitive
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--)
@@ -520,6 +521,23 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
Arrays.fill(values, EMPTY_VALUE);
}
@Override
public boolean trim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size || this.size > Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
try {
rehash(request);
}
catch(OutOfMemoryError noMemory) { return false; }
return true;
}
@Override
public void clearAndTrim(int size) {
clear();
trim(size);
}
#if !TYPE_OBJECT
protected int findIndex(KEY_TYPE key) {
if(strategy.equals(key, EMPTY_KEY_VALUE)) return containsNull ? nullIndex : -(nullIndex + 1);
@@ -549,6 +567,8 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
protected VALUE_TYPE removeIndex(int pos) {
VALUE_TYPE value = values[pos];
keys[pos] = EMPTY_KEY_VALUE;
values[pos] = EMPTY_VALUE;
size--;
onNodeRemoved(pos);
shiftKeys(pos);
@@ -35,6 +35,7 @@ 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;
import speiger.src.collections.utils.ITrimmable;
/**
* A Type Specific Custom implementation of the HashMap
@@ -43,7 +44,7 @@ import speiger.src.collections.utils.HashUtil;
* @Type(T)
* @ValueType(V)
*/
public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE
public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements ITrimmable
{
/** The Backing keys array */
protected transient KEY_TYPE[] keys;
@@ -237,7 +238,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
#endif
@Override
@Deprecated
@Primitive
public boolean containsKey(Object key) {
return findIndex(key) >= 0;
}
@@ -253,7 +254,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
#endif
@Override
@Deprecated
@ValuePrimitive
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--)
@@ -481,6 +482,23 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
Arrays.fill(values, EMPTY_VALUE);
}
@Override
public boolean trim(int size) {
int request = Math.max(minCapacity, HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor)));
if(request >= size || this.size > Math.min((int)Math.ceil(request * loadFactor), request - 1)) return false;
try {
rehash(request);
}
catch(OutOfMemoryError noMemory) { return false; }
return true;
}
@Override
public void clearAndTrim(int size) {
clear();
trim(size);
}
#if !TYPE_OBJECT
protected int findIndex(KEY_TYPE key) {
if(KEY_EQUALS_NULL(key)) return containsNull ? nullIndex : -(nullIndex + 1);
@@ -509,6 +527,8 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
protected VALUE_TYPE removeIndex(int pos) {
VALUE_TYPE value = values[pos];
keys[pos] = EMPTY_KEY_VALUE;
values[pos] = EMPTY_VALUE;
size--;
onNodeRemoved(pos);
shiftKeys(pos);
@@ -16,9 +16,6 @@ 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;
#if UNSAVE_ENUM
import sun.misc.SharedSecrets;
#endif
/**
* A Type Specific EnumMap implementation that allows for Primitive Values.
@@ -215,11 +212,7 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
protected boolean isSet(int index) { return (present[index >> 6] & (1L << index)) != 0; }
private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
#if UNSAVE_ENUM
return SharedSecrets.getJavaLangAccess().getEnumConstantsShared(keyType);
#else
return keyType.getEnumConstants();
#endif
}
class EntrySet extends AbstractObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
@@ -1931,9 +1931,9 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
#endif
int getHeight() { return state; }
void updateHeight() { state = (1 + Math.max(left == null ? 0 : left.getHeight(), right == null ? 0 : right.getHeight())); }
void updateHeight() { state = (1 + Math.max(left == null ? -1 : left.getHeight(), right == null ? -1 : right.getHeight())); }
int getBalance() { return (left == null ? 0 : left.getHeight()) - (right == null ? 0 : right.getBalance()); }
int getBalance() { return (left == null ? -1 : left.getHeight()) - (right == null ? -1 : right.getBalance()); }
boolean needsSuccessor() { return left != null && right != null; }