package loon.utils; import java.util.NoSuchElementException; import loon.LSystem; @SuppressWarnings({ "rawtypes", "unchecked" }) public class OrderedMap<K, V> extends ObjectMap<K, V> implements IArray { final TArray<K> keys; private Entries entries1, entries2; private Values values1, values2; private Keys keys1, keys2; public OrderedMap() { keys = new TArray(); } public OrderedMap(int initialCapacity) { super(initialCapacity); keys = new TArray(capacity); } public OrderedMap(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); keys = new TArray(capacity); } public OrderedMap(OrderedMap<? extends K, ? extends V> map) { super(map); keys = new TArray(map.keys); } public V put(K key, V value) { if (!containsKey(key)) keys.add(key); return super.put(key, value); } @Override public V remove(K key) { keys.removeValue(key, false); return super.remove(key); } @Override public void clear(int maximumCapacity) { keys.clear(); super.clear(maximumCapacity); } @Override public void clear() { keys.clear(); super.clear(); } public TArray<K> orderedKeys() { return keys; } @Override public Entries<K, V> iterator() { return entries(); } @Override public Entries<K, V> entries() { if (entries1 == null) { entries1 = new OrderedMapEntries(this); entries2 = new OrderedMapEntries(this); } if (!entries1.valid) { entries1.reset(); entries1.valid = true; entries2.valid = false; return entries1; } entries2.reset(); entries2.valid = true; entries1.valid = false; return entries2; } @Override public Values<V> values() { if (values1 == null) { values1 = new OrderedMapValues(this); values2 = new OrderedMapValues(this); } if (!values1.valid) { values1.reset(); values1.valid = true; values2.valid = false; return values1; } values2.reset(); values2.valid = true; values1.valid = false; return values2; } @Override public Keys<K> keys() { if (keys1 == null) { keys1 = new OrderedMapKeys(this); keys2 = new OrderedMapKeys(this); } if (!keys1.valid) { keys1.reset(); keys1.valid = true; keys2.valid = false; return keys1; } keys2.reset(); keys2.valid = true; keys1.valid = false; return keys2; } @Override public String toString() { if (size == 0) { return "{}"; } StringBuilder buffer = new StringBuilder(32); buffer.append('{'); TArray<K> keys = this.keys; for (int i = 0, n = keys.size; i < n; i++) { K key = keys.get(i); if (i > 0) buffer.append(", "); buffer.append(key); buffer.append('='); buffer.append(get(key)); } buffer.append('}'); return buffer.toString(); } static public class OrderedMapEntries<K, V> extends Entries<K, V> { private TArray<K> keys; public OrderedMapEntries(OrderedMap<K, V> map) { super(map); keys = map.keys; } @Override public void reset() { nextIndex = 0; hasNext = map.size > 0; } @Override public Entry next() { if (!hasNext) { throw new NoSuchElementException(); } if (!valid) { throw LSystem.runThrow("#iterator() cannot be used nested."); } entry.key = keys.get(nextIndex); entry.value = map.get(entry.key); nextIndex++; hasNext = nextIndex < map.size; return entry; } @Override public void remove() { if (currentIndex < 0) throw new IllegalStateException( "next must be called before remove."); map.remove(entry.key); nextIndex--; } } static public class OrderedMapKeys<K> extends Keys<K> { private TArray<K> keys; public OrderedMapKeys(OrderedMap<K, ?> map) { super(map); keys = map.keys; } @Override public void reset() { nextIndex = 0; hasNext = map.size > 0; } @Override public K next() { if (!hasNext) { throw new NoSuchElementException(); } if (!valid) { throw LSystem.runThrow("#iterator() cannot be used nested."); } K key = keys.get(nextIndex); currentIndex = nextIndex; nextIndex++; hasNext = nextIndex < map.size; return key; } @Override public void remove() { if (currentIndex < 0) throw new IllegalStateException( "next must be called before remove."); map.remove(keys.get(nextIndex - 1)); nextIndex = currentIndex; currentIndex = -1; } } static public class OrderedMapValues<V> extends Values<V> { private TArray keys; public OrderedMapValues(OrderedMap<?, V> map) { super(map); keys = map.keys; } @Override public void reset() { nextIndex = 0; hasNext = map.size > 0; } @Override public V next() { if (!hasNext) { throw new NoSuchElementException(); } if (!valid) { throw LSystem.runThrow("#iterator() cannot be used nested."); } V value = (V) map.get(keys.get(nextIndex)); currentIndex = nextIndex; nextIndex++; hasNext = nextIndex < map.size; return value; } @Override public void remove() { if (currentIndex < 0) { throw new IllegalStateException( "next must be called before remove."); } map.remove(keys.get(currentIndex)); nextIndex = currentIndex; currentIndex = -1; } } }