webit.script.util.collection.ClassIdentityHashMap Maven / Gradle / Ivy
// Copyright (c) 2013, Webit Team. All Rights Reserved.
package webit.script.util.collection;
public final class ClassIdentityHashMap {
private static final int DEFAULT_CAPACITY = 64;
private static final int MINIMUM_CAPACITY = 4;
private static final int MAXIMUM_CAPACITY = 1 << 29;
private Entry table[];
private int threshold;
private int count;
//
private final Object lock = new Object();
public ClassIdentityHashMap(int initialCapacity) {
int initlen;
if (initialCapacity > MAXIMUM_CAPACITY || initialCapacity < 0) {
initlen = MAXIMUM_CAPACITY;
} else {
initlen = MINIMUM_CAPACITY;
while (initlen < initialCapacity) {
initlen <<= 1;
}
}
init(initlen);
}
public ClassIdentityHashMap() {
init(DEFAULT_CAPACITY);
}
@SuppressWarnings("unchecked")
private void init(int initlen) {
this.table = new Entry[initlen];
this.threshold = (int) (initlen * 0.75f);
}
public int size() {
return count;
}
public V unsafeGet(final Class key) {
Entry e;
//final int id;
//id = key.hashCode();
final Entry[] tab;
//tab = table;
//final int index = id % tab.length;
//Entry e = tab[(id = System.identityHashCode(key)) & (tab.length - 1)];
//Entry e = table[index];
e = (tab = table)[key.hashCode() & (tab.length - 1)];
while (e != null) {
if (key == e.key) {
return e.value;
}
e = e.next;
}
return null;
}
public V get(Class key) {
synchronized (lock) {
return unsafeGet(key);
}
}
@SuppressWarnings("unchecked")
private void resize() {
synchronized (lock) {
if (count < threshold) {
return;
}
final Entry[] oldTable = table;
final int oldCapacity = oldTable.length;
final int newCapacity = oldCapacity << 1;
if (newCapacity > MAXIMUM_CAPACITY) {
if (threshold == MAXIMUM_CAPACITY - 1) {
throw new IllegalStateException("Capacity exhausted.");
}
threshold = MAXIMUM_CAPACITY - 1; // Gigantic map!
return;
}
final int newMark = newCapacity - 1;
final Entry newTable[] = new Entry[newCapacity];
for (int i = oldCapacity; i-- > 0;) {
int index;
for (Entry old = oldTable[i], e; old != null;) {
e = old;
old = old.next;
index = e.id & newMark;
e.next = newTable[index];
newTable[index] = e;
}
}
this.threshold = (int) (newCapacity * 0.75f);
//Note: must at Last
this.table = newTable;
}
}
@SuppressWarnings("unchecked")
private V unsafePutIfAbsent(Class key, V value) {
final int id;
//id = key.hashCode();
int index;
//final int index = id % tab.length;
Entry[] tab;
//tab = table;
Entry e = (tab = table)[index = (id = key.hashCode()) & (tab.length - 1)];
//Entry e = table[index];
for (; e != null; e = e.next) {
if (e.id == id) {
//V old = e.value;
//e.value = value;
return e.value;
}
}
if (count >= threshold) {
resize();
tab = table;
index = id & (tab.length - 1);
}
// creates the new entry.
tab[index] = new Entry(id, key, value, tab[index]);
count++;
return value;
}
public V putIfAbsent(Class key, V value) {
synchronized (lock) {
return unsafePutIfAbsent(key, value);
}
}
private static final class Entry {
final int id;
final Class key;
final V value;
Entry next;
Entry(int id, Class key, V value, Entry next) {
this.value = value;
this.id = id;
this.key = key;
this.next = next;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy