/** * Reduces the size of the backing arrays to be the specified capacity or less. If the capacity is * already less, nothing is done. If the map contains more items than the specified capacity, the * next highest power of two capacity is used instead. */ public void shrink(int maximumCapacity) { if (maximumCapacity < 0) throw new IllegalArgumentException("maximumCapacity must be >= 0: " + maximumCapacity); if (size > maximumCapacity) maximumCapacity = size; if (capacity <= maximumCapacity) return; maximumCapacity = MathUtils.nextPowerOfTwo(maximumCapacity); resize(maximumCapacity); }
/** * Clears the map and reduces the size of the backing arrays to be the specified capacity if they * are larger. */ public void clear(int maximumCapacity) { if (capacity <= maximumCapacity) { clear(); return; } hasZeroValue = false; size = 0; resize(maximumCapacity); }
private void putStash(int key, float value) { if (stashSize == stashCapacity) { // Too many pushes occurred and the stash is full, increase the table size. resize(capacity << 1); put(key, value); return; } // Store key in the stash. int index = capacity + stashSize; keyTable[index] = key; valueTable[index] = value; stashSize++; size++; }
/** Skips checks for existing keys. */ private void putResize(int key, float value) { if (key == 0) { zeroValue = value; hasZeroValue = true; return; } // Check for empty buckets. int index1 = key & mask; int key1 = keyTable[index1]; if (key1 == EMPTY) { keyTable[index1] = key; valueTable[index1] = value; if (size++ >= threshold) resize(capacity << 1); return; } int index2 = hash2(key); int key2 = keyTable[index2]; if (key2 == EMPTY) { keyTable[index2] = key; valueTable[index2] = value; if (size++ >= threshold) resize(capacity << 1); return; } int index3 = hash3(key); int key3 = keyTable[index3]; if (key3 == EMPTY) { keyTable[index3] = key; valueTable[index3] = value; if (size++ >= threshold) resize(capacity << 1); return; } push(key, value, index1, key1, index2, key2, index3, key3); }
/** * Increases the size of the backing array to accommodate the specified number of additional * items. Useful before adding many items to avoid multiple backing array resizes. */ public void ensureCapacity(int additionalCapacity) { int sizeNeeded = size + additionalCapacity; if (sizeNeeded >= threshold) resize(MathUtils.nextPowerOfTwo((int) Math.ceil(sizeNeeded / loadFactor))); }
private void push( int insertKey, float insertValue, int index1, int key1, int index2, int key2, int index3, int key3) { int[] keyTable = this.keyTable; float[] valueTable = this.valueTable; int mask = this.mask; // Push keys until an empty bucket is found. int evictedKey; float evictedValue; int i = 0, pushIterations = this.pushIterations; do { // Replace the key and value for one of the hashes. switch (MathUtils.random(2)) { case 0: evictedKey = key1; evictedValue = valueTable[index1]; keyTable[index1] = insertKey; valueTable[index1] = insertValue; break; case 1: evictedKey = key2; evictedValue = valueTable[index2]; keyTable[index2] = insertKey; valueTable[index2] = insertValue; break; default: evictedKey = key3; evictedValue = valueTable[index3]; keyTable[index3] = insertKey; valueTable[index3] = insertValue; break; } // If the evicted key hashes to an empty bucket, put it there and stop. index1 = evictedKey & mask; key1 = keyTable[index1]; if (key1 == EMPTY) { keyTable[index1] = evictedKey; valueTable[index1] = evictedValue; if (size++ >= threshold) resize(capacity << 1); return; } index2 = hash2(evictedKey); key2 = keyTable[index2]; if (key2 == EMPTY) { keyTable[index2] = evictedKey; valueTable[index2] = evictedValue; if (size++ >= threshold) resize(capacity << 1); return; } index3 = hash3(evictedKey); key3 = keyTable[index3]; if (key3 == EMPTY) { keyTable[index3] = evictedKey; valueTable[index3] = evictedValue; if (size++ >= threshold) resize(capacity << 1); return; } if (++i == pushIterations) break; insertKey = evictedKey; insertValue = evictedValue; } while (true); putStash(evictedKey, evictedValue); }
public void put(int key, float value) { if (key == 0) { zeroValue = value; if (!hasZeroValue) { hasZeroValue = true; size++; } return; } int[] keyTable = this.keyTable; // Check for existing keys. int index1 = key & mask; int key1 = keyTable[index1]; if (key == key1) { valueTable[index1] = value; return; } int index2 = hash2(key); int key2 = keyTable[index2]; if (key == key2) { valueTable[index2] = value; return; } int index3 = hash3(key); int key3 = keyTable[index3]; if (key == key3) { valueTable[index3] = value; return; } // Update key in the stash. for (int i = capacity, n = i + stashSize; i < n; i++) { if (key == keyTable[i]) { valueTable[i] = value; return; } } // Check for empty buckets. if (key1 == EMPTY) { keyTable[index1] = key; valueTable[index1] = value; if (size++ >= threshold) resize(capacity << 1); return; } if (key2 == EMPTY) { keyTable[index2] = key; valueTable[index2] = value; if (size++ >= threshold) resize(capacity << 1); return; } if (key3 == EMPTY) { keyTable[index3] = key; valueTable[index3] = value; if (size++ >= threshold) resize(capacity << 1); return; } push(key, value, index1, key1, index2, key2, index3, key3); }