package speiger.src.collections.PACKAGE.maps.impl.misc; import java.util.Comparator; import java.util.Map; import java.util.NoSuchElementException; import java.util.function.Consumer; #if TYPE_OBJECT import java.util.Objects; #endif import speiger.src.collections.PACKAGE.collections.BI_ITERATOR; #if !TYPE_OBJECT import speiger.src.collections.PACKAGE.functions.COMPARATOR; import speiger.src.collections.PACKAGE.functions.CONSUMER; #endif import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER; import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR; import speiger.src.collections.PACKAGE.maps.interfaces.MAP; import speiger.src.collections.PACKAGE.maps.interfaces.SORTED_MAP; import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET; import speiger.src.collections.PACKAGE.sets.SORTED_SET; import speiger.src.collections.PACKAGE.sets.SET; 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 && !SAME_TYPE import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER; import speiger.src.collections.VALUE_PACKAGE.lists.VALUE_LIST_ITERATOR; #endif #if !TYPE_OBJECT import speiger.src.collections.objects.collections.ObjectBidirectionalIterator; import speiger.src.collections.objects.lists.ObjectListIterator; import speiger.src.collections.objects.sets.AbstractObjectSet; import speiger.src.collections.objects.sets.ObjectSortedSet; import speiger.src.collections.objects.sets.ObjectSet; #endif /** * A Type Specific LinkedEnumMap implementation that allows for Primitive Values and faster iteration. * Unlike javas implementation this one does not jump around between a single long or long array implementation based around the enum size * This will cause a bit more memory usage but allows for a simpler implementation. * @Type(T) * @ValueType(V) */ public class LINKED_ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ENUM_MAP KEY_VALUE_GENERIC_TYPE implements SORTED_MAP KEY_VALUE_GENERIC_TYPE { /** The Backing array for links between nodes. Left 32 Bits => Previous Entry, Right 32 Bits => Next Entry */ protected long[] links; /** The First Index in the Map */ protected int firstIndex = -1; /** The Last Index in the Map */ protected int lastIndex = -1; /** * Default Constructor * @param keyType the type of Enum that should be used */ public LINKED_ENUM_MAP(Class keyType) { super(keyType); links = new long[keys.length]; } @Override public VALUE_TYPE putAndMoveToFirst(T key, VALUE_TYPE value) { int index = key.ordinal(); if(isSet(index)) { VALUE_TYPE result = values[index]; values[index] = value; moveToFirstIndex(index); return result; } set(index); values[index] = value; onNodeAdded(index); moveToFirstIndex(index); return getDefaultReturnValue(); } @Override public VALUE_TYPE putAndMoveToLast(T key, VALUE_TYPE value) { int index = key.ordinal(); if(isSet(index)) { VALUE_TYPE result = values[index]; values[index] = value; moveToLastIndex(index); return result; } set(index); values[index] = value; onNodeAdded(index); moveToLastIndex(index); return getDefaultReturnValue(); } @Override public boolean moveToFirst(T key) { int index = key.ordinal(); if(isSet(index)) { moveToFirstIndex(index); return true; } return false; } @Override public boolean moveToLast(T key) { int index = key.ordinal(); if(isSet(index)) { moveToLastIndex(index); return true; } return false; } @Override public VALUE_TYPE getAndMoveToFirst(T key) { int index = key.ordinal(); if(index < 0) return getDefaultReturnValue(); moveToFirstIndex(index); return values[index]; } @Override public VALUE_TYPE getAndMoveToLast(T key) { int index = key.ordinal(); if(index < 0) return getDefaultReturnValue(); moveToLastIndex(index); return values[index]; } @Override public COMPARATOR KEY_GENERIC_TYPE comparator() { return null; } @Override public SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(T fromKey, T toKey) { throw new UnsupportedOperationException(); } @Override public SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(T toKey) { throw new UnsupportedOperationException(); } @Override public SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(T fromKey) { throw new UnsupportedOperationException(); } @Override public T FIRST_ENTRY_KEY() { if(size == 0) throw new NoSuchElementException(); return keys[firstIndex]; } @Override public T POLL_FIRST_ENTRY_KEY() { if(size == 0) throw new NoSuchElementException(); int pos = firstIndex; firstIndex = (int)links[pos]; if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L; T result = keys[pos]; size--; values[result.ordinal()] = EMPTY_VALUE; return result; } @Override public T LAST_ENTRY_KEY() { if(size == 0) throw new NoSuchElementException(); return keys[lastIndex]; } @Override public T POLL_LAST_ENTRY_KEY() { if(size == 0) throw new NoSuchElementException(); int pos = lastIndex; lastIndex = (int)(links[pos] >>> 32); if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL; T result = keys[pos]; size--; values[result.ordinal()] = EMPTY_VALUE; return result; } @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 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 void clear() { super.clear(); firstIndex = lastIndex = -1; } protected void moveToFirstIndex(int startPos) { if(size == 1 || firstIndex == startPos) return; if(lastIndex == startPos) { lastIndex = (int)(links[startPos] >>> 32); links[lastIndex] |= 0xFFFFFFFFL; } else { long link = links[startPos]; int prev = (int)(link >>> 32); int next = (int)link; links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL); links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L); } links[firstIndex] ^= ((links[firstIndex] ^ ((startPos & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L); links[startPos] = 0xFFFFFFFF00000000L | (firstIndex & 0xFFFFFFFFL); firstIndex = startPos; } protected void moveToLastIndex(int startPos) { if(size == 1 || lastIndex == startPos) return; if(firstIndex == startPos) { firstIndex = (int)links[startPos]; links[lastIndex] |= 0xFFFFFFFF00000000L; } else { long link = links[startPos]; int prev = (int)(link >>> 32); int next = (int)link; links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL); links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L); } links[lastIndex] ^= ((links[lastIndex] ^ (startPos & 0xFFFFFFFFL)) & 0xFFFFFFFFL); links[startPos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL; lastIndex = startPos; } @Override protected void onNodeAdded(int pos) { if(size == 0) { firstIndex = lastIndex = pos; links[pos] = -1L; } else { links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL); links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL; lastIndex = pos; } } @Override protected void onNodeRemoved(int pos) { if(size == 0) firstIndex = lastIndex = -1; else if(firstIndex == pos) { firstIndex = (int)links[pos]; if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L; } else if(lastIndex == pos) { lastIndex = (int)(links[pos] >>> 32); if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL; } else { long link = links[pos]; int prev = (int)(link >>> 32); int next = (int)link; links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL); links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L); } } 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) { return LINKED_ENUM_MAP.this.moveToFirst(o.ENTRY_KEY()); } @Override public boolean moveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { return LINKED_ENUM_MAP.this.moveToLast(o.ENTRY_KEY()); } @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() { BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE()); POLL_FIRST_ENTRY_KEY(); return entry; } @Override public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLast() { BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE()); POLL_LAST_ENTRY_KEY(); return entry; } @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(T 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 @Deprecated public boolean contains(Object o) { if(o instanceof Map.Entry) { if(o instanceof MAP.Entry) return LINKED_ENUM_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY()); return LINKED_ENUM_MAP.this.containsKey(((Map.Entry)o).getKey()); } return false; } @Override @Deprecated 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 LINKED_ENUM_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE()); } Map.Entry entry = (Map.Entry)o; return LINKED_ENUM_MAP.this.remove(entry.getKey(), entry.getValue()); } return false; } @Override public int size() { return LINKED_ENUM_MAP.this.size(); } @Override public void clear() { LINKED_ENUM_MAP.this.clear(); } @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) { int oldSize = size; remove(o); return size != oldSize; } #else @Override public boolean contains(T e) { return containsKey(e); } @Override public boolean remove(T o) { int oldSize = size; remove(o); return size != oldSize; } #endif @Override public boolean add(T o) { throw new UnsupportedOperationException(); } @Override public boolean addAndMoveToFirst(T o) { throw new UnsupportedOperationException(); } @Override public boolean addAndMoveToLast(T o) { throw new UnsupportedOperationException(); } @Override public boolean moveToFirst(T o) { return LINKED_ENUM_MAP.this.moveToFirst(o); } @Override public boolean moveToLast(T o) { return LINKED_ENUM_MAP.this.moveToLast(o); } @Override public LIST_ITERATOR KEY_GENERIC_TYPE iterator() { return new KeyIterator(); } @Override public BI_ITERATOR KEY_GENERIC_TYPE iterator(T fromElement) { return new KeyIterator(fromElement); } @Override public int size() { return LINKED_ENUM_MAP.this.size(); } @Override public void clear() { LINKED_ENUM_MAP.this.clear(); } @Override public T FIRST_KEY() { return FIRST_ENTRY_KEY(); } @Override public T POLL_FIRST_KEY() { return POLL_FIRST_ENTRY_KEY(); } @Override public T LAST_KEY() { return LAST_ENTRY_KEY(); } @Override public T POLL_LAST_KEY() { return POLL_LAST_ENTRY_KEY(); } #if TYPE_OBJECT @Override public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) { int index = firstIndex; while(index != -1){ action.accept(keys[index]); index = (int)links[index]; } } #else @Override public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) { int index = firstIndex; while(index != -1){ action.accept(keys[index]); index = (int)links[index]; } } #endif @Override public COMPARATOR KEY_GENERIC_TYPE comparator() { return null; } @Override public SORTED_SET KEY_GENERIC_TYPE subSet(T fromElement, T toElement) { throw new UnsupportedOperationException(); } @Override public SORTED_SET KEY_GENERIC_TYPE headSet(T toElement) { throw new UnsupportedOperationException(); } @Override public SORTED_SET KEY_GENERIC_TYPE tailSet(T 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 LINKED_ENUM_MAP.this.size(); } @Override public void clear() { LINKED_ENUM_MAP.this.clear(); } #if VALUE_OBJECT @Override public void forEach(Consumer VALUE_SUPER_GENERIC_TYPE action) { int index = firstIndex; while(index != -1){ action.accept(values[index]); index = (int)links[index]; } } #else @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]; } } #endif } private class FastEntryIterator extends MapIterator implements ObjectListIterator { MapEntry entry = new MapEntry(); public FastEntryIterator() {} public FastEntryIterator(T 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 { MapEntry entry; public EntryIterator() {} public EntryIterator(T from) { super(from); } @Override public MAP.Entry KEY_VALUE_GENERIC_TYPE next() { return entry = new MapEntry(nextEntry()); } @Override public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() { return entry = new MapEntry(previousEntry()); } @Override public void remove() { super.remove(); entry.index = -1; } @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(T from) { super(from); } @Override public T PREVIOUS() { return keys[previousEntry()]; } @Override public T NEXT() { return keys[nextEntry()]; } @Override public void set(T e) { throw new UnsupportedOperationException(); } @Override public void add(T 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(T from) { previous = from.ordinal() - 1; index = from.ordinal(); next = from.ordinal(); } 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() { if(current == -1) throw new IllegalStateException(); ensureIndexKnown(); if(current == previous) { index--; previous = (int)(links[current] >>> 32); } else next = (int)links[current]; size--; if(previous == -1) firstIndex = next; else links[previous] ^= ((links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL); if (next == -1) lastIndex = previous; else links[next] ^= ((links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L); values[current] = EMPTY_VALUE; } 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++); } } } } 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) { VALUE_TYPE oldValue = values[index]; values[index] = value; return oldValue; } @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]); } } }