package speiger.src.collections.PACKAGE.maps.impl.immutable; import java.util.Map; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; #if !TYPE_OBJECT import speiger.src.collections.PACKAGE.collections.BI_ITERATOR; import speiger.src.collections.PACKAGE.functions.CONSUMER; import speiger.src.collections.PACKAGE.functions.COMPARATOR; #endif #if !TYPE_OBJECT && !VALUE_OBJECT import speiger.src.collections.PACKAGE.functions.consumer.BI_OBJECT_CONSUMER; #endif #if !TYPE_OBJECT && !VALUE_BOOLEAN import speiger.src.collections.PACKAGE.functions.function.PREDICATE; #endif import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER; import speiger.src.collections.PACKAGE.functions.function.FUNCTION; import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR; import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR; import speiger.src.collections.PACKAGE.maps.interfaces.SORTED_MAP; import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP; import speiger.src.collections.PACKAGE.maps.interfaces.MAP; import speiger.src.collections.PACKAGE.sets.SORTED_SET; import speiger.src.collections.PACKAGE.utils.maps.MAPS; #if !TYPE_OBJECT import speiger.src.collections.PACKAGE.utils.ARRAYS; #endif #if !TYPE_OBJECT && !VALUE_OBJECT || !VALUE_OBJECT import speiger.src.collections.objects.functions.consumer.ObjectObjectConsumer; #endif #if !TYPE_OBJECT || !VALUE_BOOLEAN #if !VALUE_OBJECT || SAME_TYPE import speiger.src.collections.objects.functions.function.Object2BooleanFunction; #endif #endif #if !SAME_TYPE import speiger.src.collections.VALUE_PACKAGE.functions.consumer.VALUE_BI_OBJECT_CONSUMER; import speiger.src.collections.VALUE_PACKAGE.functions.function.VALUE_PREDICATE; #endif #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; import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR; #if !SAME_TYPE import speiger.src.collections.VALUE_PACKAGE.functions.function.VALUE_UNARY_OPERATOR; #if !VALUE_OBJECT import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER; import speiger.src.collections.VALUE_PACKAGE.lists.VALUE_LIST_ITERATOR; import speiger.src.collections.VALUE_PACKAGE.utils.VALUE_ARRAYS; #endif #endif import speiger.src.collections.objects.collections.ObjectBidirectionalIterator; #if !TYPE_OBJECT import speiger.src.collections.objects.lists.ObjectListIterator; import speiger.src.collections.objects.sets.ObjectSortedSet; #endif 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.SanityChecks; /** * A Type Specific Custom implementation of the HashMap * Instead of using Wrapper Object Arrays for storing keys and values there is dedicated arrays for storing keys and values. * Extra to that there is a couple quality of life functions provided * @Type(T) * @ValueType(V) */ public class IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE implements SORTED_MAP KEY_VALUE_GENERIC_TYPE { /** The Backing keys array */ protected transient KEY_TYPE[] keys; /** The Backing values array */ protected transient VALUE_TYPE[] values; /** The Backing array for links between nodes. Left 32 Bits => Previous Entry, Right 32 Bits => Next Entry */ protected transient long[] links; /** If a null value is present */ protected transient boolean containsNull; /** Index of the Null Value */ protected transient int nullIndex; /** Max Index that is allowed to be searched through nullIndex - 1 */ protected transient int mask; /** The First Index in the Map */ protected int firstIndex = -1; /** The Last Index in the Map */ protected int lastIndex = -1; /** EntrySet cache */ protected transient FastEntrySet KEY_VALUE_GENERIC_TYPE entrySet; /** KeySet cache */ protected transient SET KEY_GENERIC_TYPE keySet; /** Values cache */ protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC; /** Amount of Elements stored in the HashMap */ protected int size; #if !TYPE_OBJECT || !VALUE_OBJECT /** * Helper constructor that allow to create a map from boxed values (it will unbox them) * @param keys the keys that should be put into the map * @param values the values that should be put into the map. * @throws IllegalStateException if the keys and values do not match in lenght */ public IMMUTABLE_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values) { this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR); } /** * Helper constructor that allow to create a map from boxed values (it will unbox them) * @param keys the keys that should be put into the map * @param values the values that should be put into the map. * @param loadFactor the percentage of how full the backing array can be before they resize * @throws IllegalStateException if the keys and values do not match in lenght * @throws IllegalStateException if the loadfactor is either below/equal to 0 or above/equal to 1 */ public IMMUTABLE_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, float loadFactor) { if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size"); #if TYPE_OBJECT && VALUE_OBJECT init(keys, values, 0, keys.length, loadFactor); #else if TYPE_OBJECT init(keys, VALUE_ARRAYS.unwrap(values), 0, keys.length, loadFactor); #else if VALUE_OBJECT init(ARRAYS.unwrap(keys), values, 0, keys.length, loadFactor); #else init(ARRAYS.unwrap(keys), VALUE_ARRAYS.unwrap(values), 0, keys.length, loadFactor); #endif } #endif /** * Helper constructor that allow to create a map from unboxed values * @param keys the keys that should be put into the map * @param values the values that should be put into the map. * @throws IllegalStateException if the keys and values do not match in lenght */ public IMMUTABLE_HASH_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values) { this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR); } /** * Helper constructor that allow to create a map from unboxed values * @param keys the keys that should be put into the map * @param values the values that should be put into the map. * @param loadFactor the percentage of how full the backing array can be before they resize * @throws IllegalStateException if the keys and values do not match in lenght * @throws IllegalStateException if the loadfactor is either below/equal to 0 or above/equal to 1 */ public IMMUTABLE_HASH_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values, float loadFactor) { if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size"); init(keys, values, 0, keys.length, loadFactor); } /** * A Helper constructor that allows to create a Map with exactly the same values as the provided map. * @param map the values that should be present in the map */ public IMMUTABLE_HASH_MAP(Map map) { this(map, HashUtil.DEFAULT_LOAD_FACTOR); } /** * A Helper constructor that allows to create a Map with exactly the same values as the provided map. * @param map the values that should be present in the map * @param loadFactor the percentage of how full the backing array can be before they resize * @throws IllegalStateException if the loadfactor is either below/equal to 0 or above/equal to 1 */ public IMMUTABLE_HASH_MAP(Map map, float loadFactor) { KEY_TYPE[] keys = NEW_KEY_ARRAY(map.size()); VALUE_TYPE[] values = NEW_VALUE_ARRAY(keys.length); int index = 0; for(Map.Entry entry : map.entrySet()) { keys[index] = OBJ_TO_KEY(entry.getKey()); values[index] = OBJ_TO_VALUE(entry.getValue()); index++; } init(keys, values, 0, index, loadFactor); } /** * A Type Specific Helper function that allows to create a new Map with exactly the same values as the provided map. * @param map the values that should be present in the map */ public IMMUTABLE_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map) { this(map, HashUtil.DEFAULT_LOAD_FACTOR); } /** * A Type Specific Helper function that allows to create a new Map with exactly the same values as the provided map. * @param map the values that should be present in the map * @param loadFactor the percentage of how full the backing array can be before they resize * @throws IllegalStateException if the loadfactor is either below/equal to 0 or above/equal to 1 */ public IMMUTABLE_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, float loadFactor) { KEY_TYPE[] keys = NEW_KEY_ARRAY(map.size()); VALUE_TYPE[] values = NEW_VALUE_ARRAY(keys.length); int index = 0; for(MAP.Entry KEY_VALUE_GENERIC_TYPE entry : MAPS.fastIterable(map)) { keys[index] = entry.ENTRY_KEY(); values[index] = entry.ENTRY_VALUE(); index++; } init(keys, values, 0, index, loadFactor); } protected void init(KEY_TYPE[] a, VALUE_TYPE[] b, int offset, int length, float loadFactor) { SanityChecks.checkArrayCapacity(a.length, offset, length); int newSize = HashUtil.arraySize(length+1, loadFactor); 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 prev = -1; for(int i = offset,m=offset+length;i= 0; } #endif @Override @Primitive 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 @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; return false; } @Override public VALUE_TYPE REMOVE_VALUE(KEY_TYPE key) { throw new UnsupportedOperationException(); } @Override public VALUE_TYPE REMOVE_VALUEOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) { throw new UnsupportedOperationException(); } @Override @Deprecated public CLASS_VALUE_TYPE remove(Object key) { throw new UnsupportedOperationException(); } #if !TYPE_OBJECT || !VALUE_OBJECT @Override public boolean remove(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); } #endif @Override public boolean remove(Object key, Object value) { throw new UnsupportedOperationException(); } @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 && VALUE_OBJECT @Override public VALUE_TYPE getOrDefault(Object key, VALUE_TYPE defaultValue) { int slot = findIndex(key); return slot < 0 ? defaultValue : values[slot]; } #else @Override public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) { int slot = findIndex(key); return slot < 0 ? defaultValue : values[slot]; } #endif @Override public KEY_TYPE FIRST_ENTRY_KEY() { if(size == 0) throw new NoSuchElementException(); return keys[firstIndex]; } @Override public KEY_TYPE POLL_FIRST_ENTRY_KEY() { throw new UnsupportedOperationException(); } @Override public KEY_TYPE LAST_ENTRY_KEY() { if(size == 0) throw new NoSuchElementException(); return keys[lastIndex]; } @Override public KEY_TYPE POLL_LAST_ENTRY_KEY() { throw new UnsupportedOperationException(); } @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(valuesC == null) valuesC = new Values(); return valuesC; } @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 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 boolean replace(KEY_TYPE key, VALUE_TYPE oldValue, VALUE_TYPE newValue) { throw new UnsupportedOperationException(); } @Override public VALUE_TYPE replace(KEY_TYPE key, VALUE_TYPE value) { throw new UnsupportedOperationException(); } @Override public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) { throw new UnsupportedOperationException(); } @Override public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) { throw new UnsupportedOperationException(); } @Override public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) { throw new UnsupportedOperationException(); } @Override public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) { throw new UnsupportedOperationException(); } @Override public void BULK_MERGE(MAP KEY_VALUE_GENERIC_TYPE m, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) { throw new UnsupportedOperationException(); } @Override public int size() { return size; } @Override public void clear() { throw new UnsupportedOperationException(); } #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 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) { throw new UnsupportedOperationException(); } @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 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) { throw new UnsupportedOperationException(); } @Override public boolean moveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); } @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() { throw new UnsupportedOperationException(); } @Override public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLast() { throw new UnsupportedOperationException(); } @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 public void forEach(E input, ObjectObjectConsumer action) { Objects.requireNonNull(action); if(size() <= 0) return; int index = firstIndex; while(index != -1) { action.accept(new BasicEntryKV_BRACES(keys[index], values[index]), input); index = (int)links[index]; } } @Override public boolean matchesAny(Object2BooleanFunction filter) { Objects.requireNonNull(filter); if(size() <= 0) return false; BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); int index = firstIndex; while(index != -1) { entry.set(keys[index], values[index]); if(filter.getBoolean(entry)) return true; } return false; } @Override public boolean matchesNone(Object2BooleanFunction filter) { Objects.requireNonNull(filter); if(size() <= 0) return true; BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); int index = firstIndex; while(index != -1) { entry.set(keys[index], values[index]); if(filter.getBoolean(entry)) return false; } return true; } @Override public boolean matchesAll(Object2BooleanFunction filter) { Objects.requireNonNull(filter); if(size() <= 0) return true; BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); int index = firstIndex; while(index != -1) { entry.set(keys[index], values[index]); if(!filter.getBoolean(entry)) return false; } return true; } @Override public MAP.Entry KEY_VALUE_GENERIC_TYPE findFirst(Object2BooleanFunction filter) { Objects.requireNonNull(filter); if(size() <= 0) return null; BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); int index = firstIndex; while(index != -1) { entry.set(keys[index], values[index]); if(filter.getBoolean(entry)) return entry; } return null; } @Override @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()); } return false; } @Override @Deprecated public boolean remove(Object o) { throw new UnsupportedOperationException(); } @Override public int size() { return IMMUTABLE_HASH_MAP.this.size(); } @Override public void clear() { throw new UnsupportedOperationException(); } @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) { throw new UnsupportedOperationException(); } #else @Override public boolean contains(KEY_TYPE e) { return containsKey(e); } @Override public boolean remove(KEY_TYPE o) { throw new UnsupportedOperationException(); } #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 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 IMMUTABLE_HASH_MAP.this.size(); } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public KEY_TYPE FIRST_KEY() { return FIRST_ENTRY_KEY(); } @Override public KEY_TYPE POLL_FIRST_KEY() { throw new UnsupportedOperationException(); } @Override public KEY_TYPE LAST_KEY() { return LAST_ENTRY_KEY(); } @Override public KEY_TYPE POLL_LAST_KEY() { throw new UnsupportedOperationException(); } @Override public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) { int index = firstIndex; while(index != -1){ action.accept(keys[index]); index = (int)links[index]; } } @Override public void forEach(E input, BI_OBJECT_CONSUMER KEY_VALUE_SPECIAL_GENERIC_TYPE action) { Objects.requireNonNull(action); if(size() <= 0) return; int index = firstIndex; while(index != -1){ action.accept(keys[index], input); index = (int)links[index]; } } @Override public boolean matchesAny(PREDICATE KEY_GENERIC_TYPE filter) { Objects.requireNonNull(filter); if(size() <= 0) return false; int index = firstIndex; while(index != -1){ if(filter.TEST_VALUE(keys[index])) return true; index = (int)links[index]; } return false; } @Override public boolean matchesNone(PREDICATE KEY_GENERIC_TYPE filter) { Objects.requireNonNull(filter); if(size() <= 0) return true; int index = firstIndex; while(index != -1){ if(filter.TEST_VALUE(keys[index])) return false; index = (int)links[index]; } return true; } @Override public boolean matchesAll(PREDICATE KEY_GENERIC_TYPE filter) { Objects.requireNonNull(filter); if(size() <= 0) return true; int index = firstIndex; while(index != -1){ if(!filter.TEST_VALUE(keys[index])) return false; index = (int)links[index]; } return true; } @Override public KEY_TYPE findFirst(PREDICATE KEY_GENERIC_TYPE filter) { Objects.requireNonNull(filter); if(size() <= 0) return EMPTY_KEY_VALUE; int index = firstIndex; while(index != -1){ if(filter.TEST_VALUE(keys[index])) return keys[index]; index = (int)links[index]; } return EMPTY_KEY_VALUE; } @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 IMMUTABLE_HASH_MAP.this.size(); } @Override public void clear() { throw new UnsupportedOperationException(); } @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]; } } @Override public void forEach(E input, VALUE_BI_OBJECT_CONSUMER VALUE_VALUE_SPECIAL_GENERIC_TYPE action) { Objects.requireNonNull(action); if(size() <= 0) return; int index = firstIndex; while(index != -1){ action.accept(values[index], input); index = (int)links[index]; } } @Override public boolean matchesAny(VALUE_PREDICATE VALUE_GENERIC_TYPE filter) { Objects.requireNonNull(filter); if(size() <= 0) return false; int index = firstIndex; while(index != -1){ if(filter.VALUE_TEST_VALUE(values[index])) return true; index = (int)links[index]; } return false; } @Override public boolean matchesNone(VALUE_PREDICATE VALUE_GENERIC_TYPE filter) { Objects.requireNonNull(filter); if(size() <= 0) return true; int index = firstIndex; while(index != -1){ if(filter.VALUE_TEST_VALUE(values[index])) return false; index = (int)links[index]; } return true; } @Override public boolean matchesAll(VALUE_PREDICATE VALUE_GENERIC_TYPE filter) { Objects.requireNonNull(filter); if(size() <= 0) return true; int index = firstIndex; while(index != -1){ if(!filter.VALUE_TEST_VALUE(values[index])) return false; index = (int)links[index]; } return true; } @Override public VALUE_TYPE findFirst(VALUE_PREDICATE VALUE_GENERIC_TYPE filter) { Objects.requireNonNull(filter); if(size() <= 0) return EMPTY_VALUE; int index = firstIndex; while(index != -1){ if(filter.VALUE_TEST_VALUE(values[index])) return values[index]; index = (int)links[index]; } return EMPTY_VALUE; } } private class FastEntryIterator extends MapIterator implements ObjectListIterator { MapEntry entry = new MapEntry(); 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 { public EntryIterator() {} public EntryIterator(KEY_TYPE from) { super(from); } @Override public MAP.Entry KEY_VALUE_GENERIC_TYPE next() { return new MapEntry(nextEntry()); } @Override public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() { return new MapEntry(previousEntry()); } @Override public void remove() { throw new UnsupportedOperationException(); } @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() { throw new UnsupportedOperationException(); } 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++); } } } } }