forked from Speiger/Primitive-Collections
Added over 6k tests...
- Fixed: ImmutableMaps issues thanks to the tests. Roughly the same as the rest of the maps - Fixed: RB/AVLTreeMaps issues. Roughly the same as the rest of the maps
This commit is contained in:
parent
362838c434
commit
eaa45976c7
15
Changelog.md
15
Changelog.md
|
@ -18,11 +18,16 @@
|
|||
- Fixed: Map.Entry toString wasn't writing values not like it should do.
|
||||
- Fixed: Set.hashCode now is the sum of the elements instead of a Unique HashCode based on the elements.
|
||||
- Fixed: Added missing NonNull Checks.
|
||||
- Fixed: OpenHashMap.containsValue implementation was wrong.
|
||||
- Fixed: OpenHashMap.compute/present/absent now works how it is specified in the Java Documentation
|
||||
- Fixed: OpenHashMap.merge/BulkMerge now works how it is specified in the Java Documentation
|
||||
- Fixed: OpenHashMap.keySet.remove was causing a infinite loop.
|
||||
- Fixed: OpenHashMap.mapIterator now no longer crashes in certain cases.
|
||||
- Fixed: Custom/OpenHashMap.containsValue implementation was wrong.
|
||||
- Fixed: Custom/OpenHashMap.compute/present/absent now works how it is specified in the Java Documentation
|
||||
- Fixed: Custom/OpenHashMap.merge/BulkMerge now works how it is specified in the Java Documentation
|
||||
- Fixed: Custom/Linked/OpenHashMap.keySet.remove was causing a infinite loop.
|
||||
- Fixed: Custom/Linked/OpenHashMap.entrySet.contains was not correctly comparing the entry.
|
||||
- Fixed: Custom/OpenHashMap.mapIterator now no longer crashes in certain cases.
|
||||
- Added: Custom/LinkedOpenHashMap now takes use of the improved Iterator it has for containsValue
|
||||
- Fixed: CustomOpenHashMap.keySet.forEach was basically putting out keys even if they were present
|
||||
- Fixed: ImmutableMaps issues thanks to the tests. Roughly the same as the rest of the maps
|
||||
- Fixed: RB/AVLTreeMaps issues. Roughly the same as the rest of the maps
|
||||
|
||||
### Version 0.4.5
|
||||
- Added: removeAll/retainAll(Collection c, Consumer r) which receives all the elements that got deleted from the collection
|
||||
|
|
|
@ -820,8 +820,19 @@ public class LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends CUSTOM_HASH_M
|
|||
@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());
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
int index = LINKED_CUSTOM_HASH_MAP.this.findIndex(entry.ENTRY_KEY());
|
||||
if(index >= 0) return VALUE_EQUALS(entry.ENTRY_VALUE(), LINKED_CUSTOM_HASH_MAP.this.values[index]);
|
||||
}
|
||||
else {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
#if !TYPE_OBJECT
|
||||
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
|
||||
#endif
|
||||
int index = LINKED_CUSTOM_HASH_MAP.this.findIndex((CLASS_TYPE)entry.getKey());
|
||||
if(index >= 0) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(LINKED_CUSTOM_HASH_MAP.this.values[index]));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -873,7 +884,7 @@ public class LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends CUSTOM_HASH_M
|
|||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
LINKED_CUSTOM_HASH_MAP.this.remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
|
@ -886,7 +897,7 @@ public class LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends CUSTOM_HASH_M
|
|||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
LINKED_CUSTOM_HASH_MAP.this.remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
|
|
|
@ -307,8 +307,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
#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--)
|
||||
for(int i = nullIndex;i >= 0;i--)
|
||||
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE) && VALUE_EQUALS(values[i], value)) return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -317,9 +316,12 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
@Override
|
||||
@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--)
|
||||
for(int i = nullIndex;i >= 0;i--)
|
||||
#if VALUE_OBJECT
|
||||
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE) && EQUALS_VALUE_TYPE(values[i], value)) return true;
|
||||
#else
|
||||
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE) && ((value == null && values[i] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[i], value))) return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -338,7 +340,6 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public CLASS_VALUE_TYPE remove(Object key) {
|
||||
#if !TYPE_OBJECT
|
||||
if(!(key instanceof CLASS_TYPE)) return getDefaultReturnValue();
|
||||
|
@ -495,6 +496,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
int index = findIndex(key);
|
||||
if(index < 0) {
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, getDefaultReturnValue());
|
||||
|
@ -513,6 +515,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
int index = findIndex(key);
|
||||
if(index < 0) {
|
||||
VALUE_TYPE newValue = mappingFunction.GET_VALUE(key);
|
||||
|
@ -520,11 +523,18 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
insert(-index-1, key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
return values[index];
|
||||
VALUE_TYPE newValue = values[index];
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
newValue = mappingFunction.GET_VALUE(key);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
|
||||
values[index] = newValue;
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
|
||||
Objects.requireNonNull(valueProvider);
|
||||
int index = findIndex(key);
|
||||
if(index < 0) {
|
||||
VALUE_TYPE newValue = valueProvider.VALUE_GET_KEY();
|
||||
|
@ -532,13 +542,20 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
insert(-index-1, key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
return values[index];
|
||||
VALUE_TYPE newValue = values[index];
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
newValue = valueProvider.VALUE_GET_KEY();
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
|
||||
values[index] = newValue;
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
int index = findIndex(key);
|
||||
if(index < 0) return getDefaultReturnValue();
|
||||
if(index < 0 || VALUE_EQUALS(values[index], getDefaultReturnValue())) return getDefaultReturnValue();
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, values[index]);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
removeIndex(index);
|
||||
|
@ -550,8 +567,12 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if VALUE_OBJECT
|
||||
Objects.requireNonNull(value);
|
||||
#endif
|
||||
int index = findIndex(key);
|
||||
VALUE_TYPE newValue = index < 0 ? value : mappingFunction.APPLY_VALUE(values[index], value);
|
||||
VALUE_TYPE newValue = index < 0 || VALUE_EQUALS(values[index], getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(values[index], value);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
if(index >= 0)
|
||||
removeIndex(index);
|
||||
|
@ -567,7 +588,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
for(MAP.Entry KEY_VALUE_GENERIC_TYPE entry : MAPS.fastIterable(m)) {
|
||||
KEY_TYPE key = entry.ENTRY_KEY();
|
||||
int index = findIndex(key);
|
||||
VALUE_TYPE newValue = index < 0 ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(values[index], entry.ENTRY_VALUE());
|
||||
VALUE_TYPE newValue = index < 0 || VALUE_EQUALS(values[index], getDefaultReturnValue()) ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(values[index], entry.ENTRY_VALUE());
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
if(index >= 0)
|
||||
removeIndex(index);
|
||||
|
@ -784,7 +805,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return KEY_TO_STRING(keys[index]) + "->" + VALUE_TO_STRING(values[index]);
|
||||
return KEY_TO_STRING(keys[index]) + "=" + VALUE_TO_STRING(values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -968,8 +989,19 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
@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());
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
int index = CUSTOM_HASH_MAP.this.findIndex(entry.ENTRY_KEY());
|
||||
if(index >= 0) return VALUE_EQUALS(entry.ENTRY_VALUE(), CUSTOM_HASH_MAP.this.values[index]);
|
||||
}
|
||||
else {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
#if !TYPE_OBJECT
|
||||
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
|
||||
#endif
|
||||
int index = CUSTOM_HASH_MAP.this.findIndex((CLASS_TYPE)entry.getKey());
|
||||
if(index >= 0) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(CUSTOM_HASH_MAP.this.values[index]));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -998,7 +1030,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
CUSTOM_HASH_MAP.this.remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
|
@ -1011,7 +1043,7 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
CUSTOM_HASH_MAP.this.remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
|
@ -1041,9 +1073,10 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
|
||||
@Override
|
||||
public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
|
||||
Objects.requireNonNull(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]);
|
||||
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(keys[i]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1406,9 +1439,9 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
values[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else if(pos >= 0) shiftKeys(pos);
|
||||
else if(lastReturned >= 0) shiftKeys(lastReturned);
|
||||
else {
|
||||
CUSTOM_HASH_MAP.this.remove(wrapped.GET_KEY(-pos - 1));
|
||||
CUSTOM_HASH_MAP.this.remove(wrapped.GET_KEY(-lastReturned - 1));
|
||||
return;
|
||||
}
|
||||
size--;
|
||||
|
|
|
@ -323,6 +323,33 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G
|
|||
return values[index];
|
||||
}
|
||||
|
||||
#if !VALUE_OBJECT
|
||||
@Override
|
||||
public boolean containsValue(VALUE_TYPE value) {
|
||||
int index = firstIndex;
|
||||
while(index != -1) {
|
||||
if(VALUE_EQUALS(values[index], value)) return true;
|
||||
index = (int)links[index];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
@ValuePrimitive
|
||||
public boolean containsValue(Object value) {
|
||||
int index = firstIndex;
|
||||
while(index != -1) {
|
||||
#if VALUE_OBJECT
|
||||
if(VALUE_EQUALS(values[index], value)) return true;
|
||||
#else
|
||||
if((value == null && values[index] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[index], value)) return true;
|
||||
#endif
|
||||
index = (int)links[index];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE copy() {
|
||||
LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE map = new LINKED_HASH_MAPKV_BRACES(0, loadFactor);
|
||||
|
@ -797,8 +824,16 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G
|
|||
@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());
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
int index = LINKED_HASH_MAP.this.findIndex(entry.ENTRY_KEY());
|
||||
if(index >= 0) return VALUE_EQUALS(entry.ENTRY_VALUE(), LINKED_HASH_MAP.this.values[index]);
|
||||
}
|
||||
else {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
int index = LINKED_HASH_MAP.this.findIndex(entry.getKey());
|
||||
if(index >= 0) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(LINKED_HASH_MAP.this.values[index]));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -850,7 +885,7 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G
|
|||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
LINKED_HASH_MAP.this.remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
|
@ -863,7 +898,7 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G
|
|||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
LINKED_HASH_MAP.this.remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
|
|
|
@ -288,7 +288,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
|
|||
@ValuePrimitive
|
||||
public boolean containsValue(Object value) {
|
||||
for(int i = nullIndex;i >= 0;i--)
|
||||
#if TYPE_OBJECT
|
||||
#if VALUE_OBJECT
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i]) && EQUALS_VALUE_TYPE(values[i], value)) return true;
|
||||
#else
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i]) && ((value == null && values[i] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[i], value))) return true;
|
||||
|
@ -311,7 +311,6 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
|
|||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public CLASS_VALUE_TYPE remove(Object key) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) return VALUE_TO_OBJ(getDefaultReturnValue());
|
||||
|
@ -458,6 +457,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
int index = findIndex(key);
|
||||
if(index < 0) {
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, getDefaultReturnValue());
|
||||
|
@ -476,6 +476,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
int index = findIndex(key);
|
||||
if(index < 0) {
|
||||
VALUE_TYPE newValue = mappingFunction.GET_VALUE(key);
|
||||
|
@ -494,6 +495,7 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
|
||||
Objects.requireNonNull(valueProvider);
|
||||
int index = findIndex(key);
|
||||
if(index < 0) {
|
||||
VALUE_TYPE newValue = valueProvider.VALUE_GET_KEY();
|
||||
|
@ -501,11 +503,18 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
|
|||
insert(-index-1, key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
return values[index];
|
||||
VALUE_TYPE newValue = values[index];
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
newValue = valueProvider.VALUE_GET_KEY();
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
|
||||
values[index] = newValue;
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
int index = findIndex(key);
|
||||
if(index < 0 || VALUE_EQUALS(values[index], getDefaultReturnValue())) return getDefaultReturnValue();
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, values[index]);
|
||||
|
|
|
@ -237,18 +237,34 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
|
|||
{
|
||||
KEY_TYPE o = a[i];
|
||||
if(KEY_EQUALS_NULL(o)) {
|
||||
if(!containsNull) size++;
|
||||
if(!containsNull) {
|
||||
size++;
|
||||
if(prev != -1) {
|
||||
newLinks[prev] ^= ((newLinks[prev] ^ (newSize & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
newLinks[newSize] ^= ((newLinks[newSize] ^ ((prev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
prev = newSize;
|
||||
}
|
||||
else {
|
||||
prev = firstIndex = newSize;
|
||||
newLinks[newSize] = -1L;
|
||||
}
|
||||
}
|
||||
containsNull = true;
|
||||
newValues[newSize] = b[i];
|
||||
continue;
|
||||
}
|
||||
boolean found = true;
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(o)) & newMask;
|
||||
KEY_TYPE current = newKeys[pos];
|
||||
if(KEY_EQUALS_NOT_NULL(current)) {
|
||||
if(KEY_EQUALS(current, o)) continue;
|
||||
if(KEY_EQUALS(current, o)) {
|
||||
newValues[pos] = b[i];
|
||||
continue;
|
||||
}
|
||||
while(KEY_EQUALS_NOT_NULL((current = newKeys[pos = (++pos & mask)]))) {
|
||||
if(KEY_EQUALS(current, o)) {
|
||||
found = false;
|
||||
newValues[pos] = b[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -256,7 +272,7 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
|
|||
if(found) {
|
||||
size++;
|
||||
newKeys[pos] = o;
|
||||
values[pos] = b[i];
|
||||
newValues[pos] = b[i];
|
||||
if(prev != -1) {
|
||||
newLinks[prev] ^= ((newLinks[prev] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
newLinks[pos] ^= ((newLinks[pos] ^ ((prev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
|
@ -268,7 +284,7 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
|
|||
}
|
||||
}
|
||||
}
|
||||
nullIndex = size;
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
keys = newKeys;
|
||||
values = newValues;
|
||||
|
@ -316,9 +332,11 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
|
|||
#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;
|
||||
int index = firstIndex;
|
||||
while(index != -1) {
|
||||
if(VALUE_EQUALS(values[index], value)) return true;
|
||||
index = (int)links[index];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -326,9 +344,15 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
|
|||
@Override
|
||||
@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--)
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i]) && ((value == null && values[i] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[i], value))) return true;
|
||||
int index = firstIndex;
|
||||
while(index != -1) {
|
||||
#if VALUE_OBJECT
|
||||
if(VALUE_EQUALS(values[index], value)) return true;
|
||||
#else
|
||||
if((value == null && values[index] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[index], value)) return true;
|
||||
#endif
|
||||
index = (int)links[index];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -544,6 +568,9 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
|
|||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)obj;
|
||||
Object key = entry.getKey();
|
||||
#if !TYPE_OBJECT
|
||||
if(!(key instanceof CLASS_TYPE)) return false;
|
||||
#endif
|
||||
Object value = entry.getValue();
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
return KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], value);
|
||||
|
@ -565,7 +592,7 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return KEY_TO_STRING(keys[index]) + "->" + VALUE_TO_STRING(values[index]);
|
||||
return KEY_TO_STRING(keys[index]) + "=" + VALUE_TO_STRING(values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -757,8 +784,16 @@ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_
|
|||
@Deprecated
|
||||
public boolean contains(Object o) {
|
||||
if(o instanceof Map.Entry) {
|
||||
if(o instanceof MAP.Entry) return IMMUTABLE_HASH_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
|
||||
return IMMUTABLE_HASH_MAP.this.containsKey(((Map.Entry<?, ?>)o).getKey());
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
int index = IMMUTABLE_HASH_MAP.this.findIndex(entry.ENTRY_KEY());
|
||||
if(index >= 0) return VALUE_EQUALS(entry.ENTRY_VALUE(), IMMUTABLE_HASH_MAP.this.values[index]);
|
||||
}
|
||||
else {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
int index = IMMUTABLE_HASH_MAP.this.findIndex(entry.getKey());
|
||||
if(index >= 0) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(IMMUTABLE_HASH_MAP.this.values[index]));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -233,6 +233,9 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
#endif
|
||||
@Override
|
||||
public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
if(tree == null) {
|
||||
tree = first = last = new EntryKV_BRACES(key, value, null);
|
||||
size++;
|
||||
|
@ -267,6 +270,9 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
if(tree == null) {
|
||||
tree = first = last = new EntryKV_BRACES(key, value, null);
|
||||
size++;
|
||||
|
@ -302,6 +308,9 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
#if VALUE_PRIMITIVES
|
||||
@Override
|
||||
public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
if(tree == null) {
|
||||
tree = first = last = new EntryKV_BRACES(key, value, null);
|
||||
size++;
|
||||
|
@ -510,6 +519,10 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
if(entry == null) {
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, getDefaultReturnValue());
|
||||
|
@ -528,6 +541,10 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
if(entry == null) {
|
||||
VALUE_TYPE newValue = mappingFunction.GET_VALUE(key);
|
||||
|
@ -535,11 +552,20 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
if(VALUE_EQUALS(entry.value, getDefaultReturnValue())) {
|
||||
VALUE_TYPE newValue = mappingFunction.GET_VALUE(key);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
|
||||
entry.value = newValue;
|
||||
}
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
|
||||
Objects.requireNonNull(valueProvider);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
if(entry == null) {
|
||||
VALUE_TYPE newValue = valueProvider.VALUE_GET_KEY();
|
||||
|
@ -547,13 +573,22 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
if(VALUE_EQUALS(entry.value, getDefaultReturnValue())) {
|
||||
VALUE_TYPE newValue = valueProvider.VALUE_GET_KEY();
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
|
||||
entry.value = newValue;
|
||||
}
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
if(entry == null) return getDefaultReturnValue();
|
||||
if(entry == null || VALUE_EQUALS(entry.value, getDefaultReturnValue())) return getDefaultReturnValue();
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, entry.value);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
removeNode(entry);
|
||||
|
@ -565,8 +600,12 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
VALUE_TYPE newValue = entry == null ? value : mappingFunction.APPLY_VALUE(entry.value, value);
|
||||
VALUE_TYPE newValue = entry == null || VALUE_EQUALS(entry.value, getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(entry.value, value);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
if(entry != null)
|
||||
removeNode(entry);
|
||||
|
@ -582,7 +621,7 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
for(MAP.Entry KEY_VALUE_GENERIC_TYPE entry : MAPS.fastIterable(m)) {
|
||||
KEY_TYPE key = entry.ENTRY_KEY();
|
||||
Entry KEY_VALUE_GENERIC_TYPE subEntry = findNode(key);
|
||||
VALUE_TYPE newValue = subEntry == null ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(subEntry.value, entry.ENTRY_VALUE());
|
||||
VALUE_TYPE newValue = subEntry == null || VALUE_EQUALS(subEntry.value, getDefaultReturnValue()) ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(subEntry.value, entry.ENTRY_VALUE());
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
if(subEntry != null)
|
||||
removeNode(subEntry);
|
||||
|
@ -1491,8 +1530,21 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
@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());
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
if(entry.getKey() == null) return false;
|
||||
AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = m.findNode(entry.ENTRY_KEY());
|
||||
if(subEntry != null) return VALUE_EQUALS(entry.ENTRY_VALUE(), subEntry.value);
|
||||
}
|
||||
else {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
if(entry.getKey() == null) return false;
|
||||
#if !TYPE_OBJECT
|
||||
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
|
||||
#endif
|
||||
AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = m.findNode((CLASS_TYPE)entry.getKey());
|
||||
if(subEntry != null) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(subEntry.value));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1884,8 +1936,21 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
@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());
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
if(entry.getKey() == null) return false;
|
||||
AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = AVL_TREE_MAP.this.findNode(entry.ENTRY_KEY());
|
||||
if(subEntry != null) return VALUE_EQUALS(entry.ENTRY_VALUE(), subEntry.value);
|
||||
}
|
||||
else {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
if(entry.getKey() == null) return false;
|
||||
#if !TYPE_OBJECT
|
||||
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
|
||||
#endif
|
||||
AVL_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = AVL_TREE_MAP.this.findNode((CLASS_TYPE)entry.getKey());
|
||||
if(subEntry != null) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(subEntry.value));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -2551,6 +2616,43 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
}
|
||||
|
||||
#endif
|
||||
@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;
|
||||
#if TYPE_OBJECT
|
||||
if(entry.ENTRY_KEY() == null) return false;
|
||||
#endif
|
||||
return KEY_EQUALS(key, entry.ENTRY_KEY()) && VALUE_EQUALS(value, entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)obj;
|
||||
Object otherKey = entry.getKey();
|
||||
if(otherKey == null) return false;
|
||||
Object otherValue = entry.getValue();
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
return KEY_EQUALS(key, otherKey) && VALUE_EQUALS(value, otherValue);
|
||||
#else if TYPE_OBJECT
|
||||
return otherValue instanceof CLASS_VALUE_TYPE && KEY_EQUALS(key, otherKey) && VALUE_EQUALS(value, CLASS_TO_VALUE(otherValue));
|
||||
#else if VALUE_OBJECT
|
||||
return otherKey instanceof CLASS_TYPE && KEY_EQUALS(key, CLASS_TO_KEY(otherKey)) && VALUE_EQUALS(value, otherValue);
|
||||
#else
|
||||
return otherKey instanceof CLASS_TYPE && otherValue instanceof CLASS_VALUE_TYPE && KEY_EQUALS(key, CLASS_TO_KEY(otherKey)) && VALUE_EQUALS(value, CLASS_TO_VALUE(otherValue));
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return KEY_TO_HASH(key) ^ VALUE_TO_HASH(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return KEY_TO_STRING(key) + "=" + VALUE_TO_STRING(value);
|
||||
}
|
||||
|
||||
int getHeight() { return state; }
|
||||
|
||||
void updateHeight() { state = (1 + Math.max(left == null ? -1 : left.getHeight(), right == null ? -1 : right.getHeight())); }
|
||||
|
|
|
@ -233,6 +233,9 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
#endif
|
||||
@Override
|
||||
public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
if(tree == null) {
|
||||
tree = first = last = new EntryKV_BRACES(key, value, null);
|
||||
size++;
|
||||
|
@ -267,6 +270,10 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
|
||||
if(tree == null) {
|
||||
tree = first = last = new EntryKV_BRACES(key, value, null);
|
||||
size++;
|
||||
|
@ -302,6 +309,9 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
#if VALUE_PRIMITIVES
|
||||
@Override
|
||||
public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
if(tree == null) {
|
||||
tree = first = last = new EntryKV_BRACES(key, value, null);
|
||||
size++;
|
||||
|
@ -509,6 +519,10 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
if(entry == null) {
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, getDefaultReturnValue());
|
||||
|
@ -527,6 +541,10 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
if(entry == null) {
|
||||
VALUE_TYPE newValue = mappingFunction.GET_VALUE(key);
|
||||
|
@ -534,11 +552,20 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
if(VALUE_EQUALS(entry.value, getDefaultReturnValue())) {
|
||||
VALUE_TYPE newValue = mappingFunction.GET_VALUE(key);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
|
||||
entry.value = newValue;
|
||||
}
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
|
||||
Objects.requireNonNull(valueProvider);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
if(entry == null) {
|
||||
VALUE_TYPE newValue = valueProvider.VALUE_GET_KEY();
|
||||
|
@ -546,13 +573,22 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
if(VALUE_EQUALS(entry.value, getDefaultReturnValue())) {
|
||||
VALUE_TYPE newValue = valueProvider.VALUE_GET_KEY();
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) return newValue;
|
||||
entry.value = newValue;
|
||||
}
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
if(entry == null) return getDefaultReturnValue();
|
||||
if(entry == null || VALUE_EQUALS(entry.value, getDefaultReturnValue())) return getDefaultReturnValue();
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, entry.value);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
removeNode(entry);
|
||||
|
@ -564,8 +600,12 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
|
||||
@Override
|
||||
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
#if TYPE_OBJECT
|
||||
Objects.requireNonNull(key);
|
||||
#endif
|
||||
Entry KEY_VALUE_GENERIC_TYPE entry = findNode(key);
|
||||
VALUE_TYPE newValue = entry == null ? value : mappingFunction.APPLY_VALUE(entry.value, value);
|
||||
VALUE_TYPE newValue = entry == null || VALUE_EQUALS(entry.value, getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(entry.value, value);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
if(entry != null)
|
||||
removeNode(entry);
|
||||
|
@ -581,7 +621,7 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
for(MAP.Entry KEY_VALUE_GENERIC_TYPE entry : MAPS.fastIterable(m)) {
|
||||
KEY_TYPE key = entry.ENTRY_KEY();
|
||||
Entry KEY_VALUE_GENERIC_TYPE subEntry = findNode(key);
|
||||
VALUE_TYPE newValue = subEntry == null ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(subEntry.value, entry.ENTRY_VALUE());
|
||||
VALUE_TYPE newValue = subEntry == null || VALUE_EQUALS(subEntry.value, getDefaultReturnValue()) ? entry.ENTRY_VALUE() : mappingFunction.APPLY_VALUE(subEntry.value, entry.ENTRY_VALUE());
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
if(subEntry != null)
|
||||
removeNode(subEntry);
|
||||
|
@ -1545,8 +1585,21 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
@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());
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
if(entry.getKey() == null) return false;
|
||||
RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = m.findNode(entry.ENTRY_KEY());
|
||||
if(subEntry != null) return VALUE_EQUALS(entry.ENTRY_VALUE(), subEntry.value);
|
||||
}
|
||||
else {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
if(entry.getKey() == null) return false;
|
||||
#if !TYPE_OBJECT
|
||||
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
|
||||
#endif
|
||||
RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = m.findNode((CLASS_TYPE)entry.getKey());
|
||||
if(subEntry != null) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(subEntry.value));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1938,8 +1991,21 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
@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());
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
if(entry.getKey() == null) return false;
|
||||
RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = RB_TREE_MAP.this.findNode(entry.ENTRY_KEY());
|
||||
if(subEntry != null) return VALUE_EQUALS(entry.ENTRY_VALUE(), subEntry.value);
|
||||
}
|
||||
else {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
if(entry.getKey() == null) return false;
|
||||
#if !TYPE_OBJECT
|
||||
if(!(entry.getKey() instanceof CLASS_TYPE)) return false;
|
||||
#endif
|
||||
RB_TREE_MAP.Entry KEY_VALUE_GENERIC_TYPE subEntry = RB_TREE_MAP.this.findNode((CLASS_TYPE)entry.getKey());
|
||||
if(subEntry != null) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(subEntry.value));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -2620,6 +2686,43 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
}
|
||||
|
||||
#endif
|
||||
@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;
|
||||
#if TYPE_OBJECT
|
||||
if(entry.ENTRY_KEY() == null) return false;
|
||||
#endif
|
||||
return KEY_EQUALS(key, entry.ENTRY_KEY()) && VALUE_EQUALS(value, entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)obj;
|
||||
Object otherKey = entry.getKey();
|
||||
if(otherKey == null) return false;
|
||||
Object otherValue = entry.getValue();
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
return KEY_EQUALS(key, otherKey) && VALUE_EQUALS(value, otherValue);
|
||||
#else if TYPE_OBJECT
|
||||
return otherValue instanceof CLASS_VALUE_TYPE && KEY_EQUALS(key, otherKey) && VALUE_EQUALS(value, CLASS_TO_VALUE(otherValue));
|
||||
#else if VALUE_OBJECT
|
||||
return otherKey instanceof CLASS_TYPE && KEY_EQUALS(key, CLASS_TO_KEY(otherKey)) && VALUE_EQUALS(value, otherValue);
|
||||
#else
|
||||
return otherKey instanceof CLASS_TYPE && otherValue instanceof CLASS_VALUE_TYPE && KEY_EQUALS(key, CLASS_TO_KEY(otherKey)) && VALUE_EQUALS(value, CLASS_TO_VALUE(otherValue));
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return KEY_TO_HASH(key) ^ VALUE_TO_HASH(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return KEY_TO_STRING(key) + "=" + VALUE_TO_STRING(value);
|
||||
}
|
||||
|
||||
boolean isBlack() {
|
||||
return (state & BLACK) != 0;
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
package speiger.src.collections.objects.map;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.testing.MapTestSuiteBuilder;
|
||||
import com.google.common.collect.testing.TestStringMapGenerator;
|
||||
import com.google.common.collect.testing.features.CollectionFeature;
|
||||
import com.google.common.collect.testing.features.CollectionSize;
|
||||
import com.google.common.collect.testing.features.MapFeature;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
|
||||
|
||||
@SuppressWarnings("javadoc")
|
||||
public final class MapTest extends TestCase
|
||||
{
|
||||
public static Test suite()
|
||||
{
|
||||
return suite("Object2ObjectOpenHashMap", Object2ObjectOpenHashMap::new);
|
||||
}
|
||||
|
||||
public static Test suite(String name, Supplier<Map<String, String>> factory)
|
||||
{
|
||||
return MapTestSuiteBuilder.using(new TestStringMapGenerator()
|
||||
{
|
||||
@Override
|
||||
protected Map<String, String> create(Map.Entry<String, String>[] entries)
|
||||
{
|
||||
Map<String, String> map = factory.get();
|
||||
for(Map.Entry<String, String> entry : entries)
|
||||
{
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}).named(name).withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE, MapFeature.ALLOWS_NULL_KEYS, MapFeature.ALLOWS_NULL_VALUES, MapFeature.ALLOWS_ANY_NULL_QUERIES, CollectionFeature.SUPPORTS_ITERATOR_REMOVE).createTestSuite();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package speiger.src.collections.objects.map;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.collect.testing.MapTestSuiteBuilder;
|
||||
import com.google.common.collect.testing.TestStringMapGenerator;
|
||||
import com.google.common.collect.testing.features.CollectionFeature;
|
||||
import com.google.common.collect.testing.features.CollectionSize;
|
||||
import com.google.common.collect.testing.features.MapFeature;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
import speiger.src.collections.objects.maps.impl.customHash.Object2ObjectLinkedOpenCustomHashMap;
|
||||
import speiger.src.collections.objects.maps.impl.customHash.Object2ObjectOpenCustomHashMap;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
|
||||
import speiger.src.collections.objects.maps.impl.immutable.ImmutableObject2ObjectOpenHashMap;
|
||||
import speiger.src.collections.objects.maps.impl.tree.Object2ObjectAVLTreeMap;
|
||||
import speiger.src.collections.objects.maps.impl.tree.Object2ObjectRBTreeMap;
|
||||
import speiger.src.collections.objects.utils.ObjectStrategy;
|
||||
|
||||
@SuppressWarnings("javadoc")
|
||||
public class ObjectMapTests extends TestCase
|
||||
{
|
||||
public static Test suite()
|
||||
{
|
||||
TestSuite suite = new TestSuite("Maps");
|
||||
suite.addTest(suite("HashMap", Object2ObjectOpenHashMap::new, true));
|
||||
suite.addTest(suite("LinkedHashMap", Object2ObjectLinkedOpenHashMap::new, true));
|
||||
suite.addTest(suite("CustomHashMap", () -> new Object2ObjectOpenCustomHashMap<>(Strategy.INSTANCE), true));
|
||||
suite.addTest(suite("LinkedCustomHashMap", () -> new Object2ObjectLinkedOpenCustomHashMap<>(Strategy.INSTANCE), true));
|
||||
suite.addTest(suite("RBTreeMap", () -> new Object2ObjectRBTreeMap<String, String>(Comparator.naturalOrder()), false));
|
||||
suite.addTest(suite("AVLTreeMap", () -> new Object2ObjectAVLTreeMap<String, String>(Comparator.naturalOrder()), false));
|
||||
suite.addTest(immutableSuit("ImmutableMap", ImmutableObject2ObjectOpenHashMap::new));
|
||||
return suite;
|
||||
}
|
||||
|
||||
public static Test suite(String name, Supplier<Map<String, String>> factory, boolean allowNull)
|
||||
{
|
||||
MapTestSuiteBuilder<String, String> builder = MapTestSuiteBuilder.using(new TestStringMapGenerator() {
|
||||
@Override
|
||||
protected Map<String, String> create(Map.Entry<String, String>[] entries) {
|
||||
Map<String, String> map = factory.get();
|
||||
for(Map.Entry<String, String> entry : entries) {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}).named(name).withFeatures(CollectionSize.ANY, MapFeature.GENERAL_PURPOSE, MapFeature.ALLOWS_NULL_VALUES, CollectionFeature.SUPPORTS_ITERATOR_REMOVE);
|
||||
if(allowNull) builder.withFeatures(MapFeature.ALLOWS_NULL_KEYS, MapFeature.ALLOWS_ANY_NULL_QUERIES);
|
||||
return builder.createTestSuite();
|
||||
}
|
||||
|
||||
public static Test immutableSuit(String name, BiFunction<String[], String[], Map<String, String>> factory) {
|
||||
MapTestSuiteBuilder<String, String> builder = MapTestSuiteBuilder.using(new TestStringMapGenerator() {
|
||||
@Override
|
||||
protected Map<String, String> create(Map.Entry<String, String>[] entries) {
|
||||
String[] keys = new String[entries.length];
|
||||
String[] values = new String[entries.length];
|
||||
for(int i = 0;i<entries.length;i++) {
|
||||
keys[i] = entries[i].getKey();
|
||||
values[i] = entries[i].getValue();
|
||||
}
|
||||
return factory.apply(keys, values);
|
||||
}
|
||||
}).named(name).withFeatures(CollectionSize.ANY, MapFeature.ALLOWS_NULL_KEYS, MapFeature.ALLOWS_NULL_VALUES, MapFeature.ALLOWS_ANY_NULL_QUERIES);
|
||||
return builder.createTestSuite();
|
||||
}
|
||||
|
||||
private static class Strategy implements ObjectStrategy<String>
|
||||
{
|
||||
static final Strategy INSTANCE = new Strategy();
|
||||
|
||||
@Override
|
||||
public int hashCode(String o) {
|
||||
return Objects.hashCode(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(String key, String value) {
|
||||
return Objects.equals(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue