package org.simpleflatmapper.map.context.impl; import org.simpleflatmapper.map.context.Key; import java.util.Arrays; public final class KeyObjectStore { private static final int DEFAULT_SIZE = 16; private static final int MAXIMUM_CAPACITY = 1 << 30; private Key[] keys; private Object[] values; private int size; private int nbValues; private int resizeThreshold; private int mask; public KeyObjectStore() { nbValues = 0; initSize(DEFAULT_SIZE); } private int calculateMask(int size) { return size - 1; } public void put(Key key, Object value) { checkCapacity(); int index = getIndex(key); if (index >= 0) { throw new IllegalArgumentException("Already has key " + key); } setValue(key, value, index + size); } private void checkCapacity() { if (nbValues > resizeThreshold) resize(); } public Object get(Key key) { int index = getIndex(key); if (index >= 0) { return getValue(index); } return null; } private void setValue(Key key, Object value, int index) { keys[index] = key; values[index] = value; nbValues++; } private Object getValue(int index) { return values[index]; } private int getIndex(Key key) { int hashCode = key.hashCode(); int startIndex = toIndex(hashCode); for(int i = startIndex; i < size; i++) { Key k = keys[i]; if (k == null) return i - size; if (hashCode == k.hashCode() && key.equals(k)) { return i; } } for(int i = 0; i < startIndex; i++) { Key k = keys[i]; if (k == null) return i - size; if (hashCode == k.hashCode() && key.equals(k)) { return i; } } throw new IllegalStateException("Could not find the key or a free sport..."); } private void resize() { if (size < MAXIMUM_CAPACITY) { Key[] oldKeys = keys; Object[] oldValues = values; int oldSize = size; initSize(size << 1); for (int i = 0; i < oldSize; i++) { Key k = oldKeys[i]; if (k != null) { int ki = freeSpot(k); keys[ki] = k; values[ki] = oldValues[i]; } } } } private int freeSpot(Key key) { int hashCode = key.hashCode(); int startIndex = toIndex(hashCode); for(int i = startIndex; i < size; i++) { Key k = keys[i]; if (k == null) return i; } for(int i = 0; i < startIndex; i++) { Key k = keys[i]; if (k == null) return i; } throw new IllegalStateException("Could not find the key or a free sport..."); } private void initSize(int newSize) { keys = new Key[newSize]; values = new Object[newSize]; mask = calculateMask(newSize); size = newSize; resizeThreshold = size >> 1; } private int toIndex(int hashCode) { return (hashCode & mask); } public void clear() { Arrays.fill(keys, null); Arrays.fill(values, null); nbValues = 0; } }