ProtocolLib/src/main/java/com/comphenix/protocol/collections/IntegerMap.java

125 lines
3.2 KiB
Java

package com.comphenix.protocol.collections;
import com.comphenix.protocol.utility.IntegerMath;
import com.google.common.base.Preconditions;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a very quick integer-based lookup map, with a fixed key space size.
* <p>
* Integers must be non-negative.
* @author Kristian
*/
public class IntegerMap<T> {
private T[] array;
private int size;
/**
* Construct a new integer map with a default capacity.
*/
public IntegerMap() {
this(8);
}
/**
* Construct a new integer map with a given capacity.
* @param initialCapacity - the capacity.
*/
public IntegerMap(int initialCapacity) {
@SuppressWarnings("unchecked")
T[] backingArray = (T[]) new Object[initialCapacity];
this.array = backingArray;
this.size = 0;
}
/**
* Associate an integer key with the given value.
* @param key - the integer key. Cannot be negative.
* @param value - the value. Cannot be NULL.
* @return The previous association, or NULL if not found.
*/
public T put(int key, T value) {
ensureCapacity(key);
T old = array[key];
array[key] = Preconditions.checkNotNull(value, "value cannot be NULL");
if (old == null) ++size;
return old;
}
/**
* Remove an association from the map.
* @param key - the key of the association to remove.
* @return The old associated value, or NULL.
*/
public T remove(int key) {
T old = array[key];
array[key] = null;
if (old != null) --size;
return old;
}
/**
* Resize the backing array to fit the given key.
* @param key - the key.
*/
protected void ensureCapacity(int key) {
// Don't resize if the key fits
if (key < 0) throw new IllegalArgumentException("Negative key values are not permitted.");
if (key < array.length) return;
// Fast calculation of the new size.
// See IntMath#ceilingPowerOfTwo in newer guava versions.
int newLength = IntegerMath.nextPowerOfTwo(key);
this.array = Arrays.copyOf(array, newLength);
}
/**
* Retrieve the number of mappings in this map.
* @return The number of mapping.
*/
public int size() {
return size;
}
/**
* Retrieve the value associated with a given key.
* @param key - the key.
* @return The value, or NULL if not found.
*/
public T get(int key) {
return key >= 0 && key < array.length ? array[key] : null;
}
/**
* Determine if the given key exists in the map.
* @param key - the key to check.
* @return TRUE if it does, FALSE otherwise.
*/
public boolean containsKey(int key) {
return get(key) != null;
}
/**
* Convert the current map to an Integer map.
* @return The Integer map.
*/
public Map<Integer, Object> toMap() {
final Map<Integer, Object> map = new HashMap<>();
for (int i = 0; i < array.length; i++) {
if (array[i] != null) {
map.put(i, array[i]);
}
}
return map;
}
}