package speiger.src.collections.PACKAGE.maps.impl.misc; import java.util.Map; import java.util.NoSuchElementException; #if VALUE_OBJECT import java.util.Objects; #endif import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION; import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION; import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR; #if !VALUE_OBJECT import speiger.src.collections.objects.collections.ObjectIterator; #endif import speiger.src.collections.objects.maps.abstracts.ABSTRACT_MAP; import speiger.src.collections.objects.maps.interfaces.MAP; import speiger.src.collections.objects.sets.AbstractObjectSet; import speiger.src.collections.objects.sets.ObjectSet; import sun.misc.SharedSecrets; public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE { protected final Class keyType; protected transient final T[] keys; protected transient final VALUE_TYPE[] values; protected transient final long[] present; protected int size = 0; protected transient ObjectSet entrySet; protected transient ObjectSet keySet; protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC; public ENUM_MAP(Class keyType) { this.keyType = keyType; keys = getKeyUniverse(keyType); values = NEW_VALUE_ARRAY(keys.length); present = new long[((keys.length - 1) >> 6) + 1]; } @Override public VALUE_TYPE put(T key, VALUE_TYPE value) { int index = key.ordinal(); if(isSet(index)) { VALUE_TYPE result = values[index]; values[index] = value; return result; } set(index); values[index] = value; return getDefaultReturnValue(); } @Override public VALUE_TYPE putIfAbsent(T key, VALUE_TYPE value) { int index = key.ordinal(); if(isSet(index)) return values[index]; set(index); values[index] = value; return getDefaultReturnValue(); } #if VALUE_PRIMITIVES @Override public VALUE_TYPE addTo(T key, VALUE_TYPE value) { int index = key.ordinal(); if(isSet(index)) { VALUE_TYPE result = values[index]; values[index] += value; return result; } set(index); values[index] = value; return getDefaultReturnValue(); } #endif @Override public boolean containsKey(Object key) { return isSet(((T)key).ordinal()); } #if VALUE_OBJECT @Override public boolean containsValue(Object value) { for(int i = 0;i ENTRY_SET() { if(entrySet == null) entrySet = new EntrySet(); return entrySet; } @Override public ObjectSet keySet() { if(keySet == null) keySet = new KeySet(); return keySet; } @Override public VALUE_COLLECTION VALUE_GENERIC_TYPE values() { if(valuesC == null) valuesC = new Values(); return valuesC; } protected void onNodeAdded(int index) { } protected void onNodeRemoved(int index) { } protected void set(int index) { present[index >> 6] |= (1L << index); onNodeAdded(index); } protected void clear(int index) { present[index >> 6] &= ~(1L << index); onNodeRemoved(index); } protected boolean isSet(int index) { return (present[index >> 6] & (1L << index)) != 0; } private static > K[] getKeyUniverse(Class keyType) { // return keyType.getEnumConstants(); return SharedSecrets.getJavaLangAccess().getEnumConstantsShared(keyType); } class EntrySet extends AbstractObjectSet { @Override public boolean contains(Object o) { if(o instanceof Map.Entry) return containsKey(((Map.Entry)o).getKey()); return false; } @Override public boolean remove(Object o) { if(o instanceof Map.Entry) { if(o instanceof MAP.Entry) { MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o; return ENUM_MAP.this.remove(entry.getKey(), entry.ENTRY_VALUE()); } Map.Entry entry = (java.util.Map.Entry)o; return ENUM_MAP.this.remove(entry.getKey(), entry.getValue()); } return false; } @Override public ObjectIterator iterator() { return new EntryIterator(); } @Override public int size() { return ENUM_MAP.this.size(); } @Override public void clear() { ENUM_MAP.this.clear(); } } class KeySet extends AbstractObjectSet { @Override public boolean contains(Object o) { return containsKey(o); } @Override public boolean remove(Object o) { int size = size(); ENUM_MAP.this.remove(o); return size != size(); } @Override public ObjectIterator iterator() { return new KeyIterator(); } @Override public int size() { return ENUM_MAP.this.size(); } @Override public void clear() { ENUM_MAP.this.clear(); } } class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE { @Override public boolean add(VALUE_TYPE o) { throw new UnsupportedOperationException(); } #if TYPE_OBJECT @Override public boolean contains(Object e) { return containsValue(e); } #else @Override public boolean contains(VALUE_TYPE e) { return containsValue(e); } #endif @Override public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() { return new ValueIterator(); } @Override public int size() { return ENUM_MAP.this.size(); } @Override public void clear() { ENUM_MAP.this.clear(); } } class EntryIterator extends MapIterator implements ObjectIterator { @Override public MAP.Entry KEY_VALUE_GENERIC_TYPE next() { int index = nextEntry(); return new BasicEntry<>(keys[index], values[index]); } } class KeyIterator extends MapIterator implements ObjectIterator { @Override public T next() { return keys[nextEntry()]; } } class ValueIterator extends MapIterator implements VALUE_ITERATOR VALUE_GENERIC_TYPE { @Override public VALUE_TYPE VALUE_NEXT() { return values[nextEntry()]; } } class MapIterator { int index; int lastReturnValue = -1; int nextIndex = -1; public boolean hasNext() { if(nextIndex == -1 && index < values.length) { while(index < values.length && !isSet(index++)); nextIndex = index-1; if(!isSet(nextIndex)) nextIndex = -1; } return nextIndex != -1; } public int nextEntry() { if(!hasNext()) throw new NoSuchElementException(); lastReturnValue = nextIndex; return nextIndex; } public void remove() { if(lastReturnValue == -1) throw new IllegalStateException(); clear(lastReturnValue); values[lastReturnValue] = EMPTY_VALUE; } } }