public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) { return intercept(new EconomicMapImpl<>(strategy, other, isSet)); }
private int findHash(K key) { int index = getHashArray(getHashIndex(key)) - 1; if (index != -1) { Object entryKey = getKey(index); if (compareKeys(key, entryKey)) { return index; } else { Object entryValue = getRawValue(index); if (entryValue instanceof CollisionLink) { return findWithCollision(key, (CollisionLink) entryValue); } } } return -1; }
/** * Compresses the graph if there is a large number of deleted entries and returns the translated * new next index. */ private int maybeCompress(int nextIndex) { if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) { return compressLarge(nextIndex); } return nextIndex; }
throw new UnsupportedOperationException("null not supported as key!"); int index = find(key); if (index != -1) { Object oldValue = getValue(index); setValue(index, value); return (V) oldValue; entries = new Object[INITIAL_CAPACITY << 1]; } else if (entries.length == nextEntryIndex << 1) { grow(); setKey(nextEntryIndex, key); setValue(nextEntryIndex, value); totalEntries++; if (hasHashArray()) { boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1))); putHashEntry(key, nextEntryIndex, rehashOnCollision); } else if (totalEntries > getHashThreshold()) { createHash();
private int findAndRemoveHash(Object key) { int hashIndex = getHashIndex(key); int index = getHashArray(hashIndex) - 1; if (index != -1) { Object entryKey = getKey(index); if (compareKeys(key, entryKey)) { Object value = getRawValue(index); int nextIndex = -1; if (value instanceof CollisionLink) { CollisionLink collisionLink = (CollisionLink) value; nextIndex = collisionLink.next; } setHashArray(hashIndex, nextIndex + 1); return index; } else { Object entryValue = getRawValue(index); if (entryValue instanceof CollisionLink) { return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index); } } } return -1; }
private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) { int hashIndex = getHashIndex(key); int oldIndex = getHashArray(hashIndex) - 1; if (oldIndex != -1 && rehashOnCollision) { this.createHash(); return; } setHashArray(hashIndex, entryIndex + 1); Object value = getRawValue(entryIndex); if (oldIndex != -1) { assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle"; if (value instanceof CollisionLink) { CollisionLink collisionLink = (CollisionLink) value; setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex)); } else { setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex)); } } else { if (value instanceof CollisionLink) { CollisionLink collisionLink = (CollisionLink) value; setRawValue(entryIndex, collisionLink.value); } } }
@SuppressWarnings("unchecked") @Override public V removeKey(K key) { if (key == null) { throw new UnsupportedOperationException("null not supported as key!"); } int index; if (hasHashArray()) { index = this.findAndRemoveHash(key); } else { index = this.findLinear(key); } if (index != -1) { Object value = getValue(index); remove(index); return (V) value; } return null; }
private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) { int index; Object entryKey; CollisionLink entryValue = initialEntryValue; int lastIndex = initialIndexValue; while (true) { CollisionLink collisionLink = entryValue; index = collisionLink.next; entryKey = getKey(index); if (compareKeys(key, entryKey)) { Object value = getRawValue(index); if (value instanceof CollisionLink) { CollisionLink thisCollisionLink = (CollisionLink) value; setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next)); } else { setRawValue(lastIndex, collisionLink.value); } return index; } else { Object value = getRawValue(index); if (value instanceof CollisionLink) { entryValue = (CollisionLink) getRawValue(index); lastIndex = index; } else { return -1; } } } }
int newNextIndex = remaining; for (int i = 0; i < totalEntries; ++i) { Object key = getKey(i); if (i == nextIndex) { newNextIndex = z; newEntries[(z << 1) + 1] = getValue(i); z++; totalEntries = z; deletedEntries = 0; if (z <= getHashThreshold()) { this.hashArray = null; } else { createHash();
private int findWithCollision(K key, CollisionLink initialEntryValue) { int index; Object entryKey; CollisionLink entryValue = initialEntryValue; while (true) { CollisionLink collisionLink = entryValue; index = collisionLink.next; entryKey = getKey(index); if (compareKeys(key, entryKey)) { return index; } else { Object value = getRawValue(index); if (value instanceof CollisionLink) { entryValue = (CollisionLink) getRawValue(index); } else { return -1; } } } }
/** * Creates a new map that guarantees insertion order on the key set and initializes with a * specified capacity. * * @since 1.0 */ static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) { return EconomicMapImpl.create(strategy, initialCapacity, false); }
private int findLinear(K key) { for (int i = 0; i < totalEntries; i++) { Object entryKey = entries[i << 1]; if (entryKey != null && compareKeys(key, entryKey)) { return i; } } return -1; }
@Override public boolean containsKey(K key) { return find(key) != -1; }
@Override public boolean contains(K element) { return containsKey(element); }
private void grow() { int entriesLength = entries.length; int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2); if (newSize > MAX_ELEMENT_COUNT) { throw new UnsupportedOperationException("map grown too large!"); } Object[] newEntries = new Object[newSize << 1]; System.arraycopy(entries, 0, newEntries, 0, entriesLength); entries = newEntries; if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) || (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) { // Rehash in order to change number of bits reserved for hash indices. createHash(); } }
throw new UnsupportedOperationException("null not supported as key!"); int index = find(key); if (index != -1) { Object oldValue = getValue(index); setValue(index, value); return (V) oldValue; entries = new Object[INITIAL_CAPACITY << 1]; } else if (entries.length == nextEntryIndex << 1) { grow(); setKey(nextEntryIndex, key); setValue(nextEntryIndex, value); totalEntries++; if (hasHashArray()) { boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1))); putHashEntry(key, nextEntryIndex, rehashOnCollision); } else if (totalEntries > getHashThreshold()) { createHash();
private int findAndRemoveHash(Object key) { int hashIndex = getHashIndex(key); int index = getHashArray(hashIndex) - 1; if (index != -1) { Object entryKey = getKey(index); if (compareKeys(key, entryKey)) { Object value = getRawValue(index); int nextIndex = -1; if (value instanceof CollisionLink) { CollisionLink collisionLink = (CollisionLink) value; nextIndex = collisionLink.next; } setHashArray(hashIndex, nextIndex + 1); return index; } else { Object entryValue = getRawValue(index); if (entryValue instanceof CollisionLink) { return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index); } } } return -1; }
private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) { int hashIndex = getHashIndex(key); int oldIndex = getHashArray(hashIndex) - 1; if (oldIndex != -1 && rehashOnCollision) { this.createHash(); return; } setHashArray(hashIndex, entryIndex + 1); Object value = getRawValue(entryIndex); if (oldIndex != -1) { assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle"; if (value instanceof CollisionLink) { CollisionLink collisionLink = (CollisionLink) value; setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex)); } else { setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex)); } } else { if (value instanceof CollisionLink) { CollisionLink collisionLink = (CollisionLink) value; setRawValue(entryIndex, collisionLink.value); } } }