package de.spieleck.util;
import java.io.Serializable;
import java.util.Dictionary;
import java.util.Enumeration;
public class SpeedHashtable
extends Dictionary
implements Serializable
{
private static final int INIT_SIZE = 5;
private final static int HASHSTEP = 5;
private Object[] table;
protected int capacity;
protected int capacity1;
protected int used;
private double loadFactor;
private int usedLimit;
public SpeedHashtable()
{
this(INIT_SIZE, 0.75);
}
public SpeedHashtable(int n)
{
this(n, 0.75);
}
public SpeedHashtable(double loadFactor)
{
this(INIT_SIZE, loadFactor);
}
public SpeedHashtable(int n, double loadFactor)
{
this.loadFactor = loadFactor;
n = (int)((n + 1) / loadFactor);
int h = 4;
while (h < n)
h += h;
used = 0;
internalInit(h);
}
private final void internalInit(int size)
{
capacity = size;
capacity1 = size - 1;
table = new Object[size << 1];
usedLimit = (int)(size * loadFactor);
}
public final int size()
{
return used;
}
public final boolean isEmpty()
{
return used == 0;
}
private final int nextIndex(int i)
{
return i < HASHSTEP
? capacity + i - HASHSTEP
: i - HASHSTEP;
}
private final int firstIndex(Object key)
{
return hashCode(key) & capacity1;
}
protected int hashCode(Object key)
{
return key.hashCode();
}
public final boolean containsKey(Object key)
{
return get(key) != null;
}
protected int lastGetIndex;
protected Object lastKey;
public Object get(Object key)
{
if (key != null)
{
lastKey = key;
int i = firstIndex(key);
for (; table[i] != null; i = nextIndex(i))
if (table[i].equals(key))
{
lastGetIndex = i;
return table[i | capacity];
}
lastGetIndex = i;
}
return null;
}
public Object put(Object key, Object value)
{
if (value == null || key == null)
throw new NullPointerException();
return unsafePut(key, value);
}
public Object replaceLastGet(Object value)
{
if (value == null)
throw new NullPointerException();
int h = lastGetIndex | capacity;
Object old = table[h];
table[h] = value;
if (old == null)
{
table[lastGetIndex] = lastKey;
if (++used > usedLimit)
rehash();
}
return old;
}
protected final Object unsafePut(Object key, Object value)
{
int h;
for (h = firstIndex(key); table[h] != null; h = nextIndex(h))
if (key.equals(table[h]))
{
h |= capacity;
Object old = table[h];
table[h] = value;
return old;
}
if (++used > usedLimit)
{
rehash();
for (h = firstIndex(key);
table[h] != null;
h = nextIndex(h))
;
}
table[h] = key;
table[h | capacity] = value;
return null;
}
private final void rehash()
{
int j;
int oldCap = capacity;
Object[] oTable = table;
internalInit(capacity * 2);
for (int i = oldCap; i > 0;)
{
if (oTable[--i] != null)
{
for (j = firstIndex(oTable[i]);
table[j] != null;
j = nextIndex(j))
;
table[j] = oTable[i];
table[j | capacity] = oTable[i | oldCap];
}
}
}
public void append(SpeedHashtable tab2)
{
Enumeration en = tab2.keys();
while (en.hasMoreElements())
{
Object key = en.nextElement();
unsafePut(key, tab2.get(key));
}
}
public Object remove(Object key)
{
if (used > 0)
{
for (int i = firstIndex(key);
table[i] != null;
i = nextIndex(i))
if (table[i].equals(key))
{
Object obj = table[i];
do
{
table[i] = null;
table[i | capacity] = null;
int j = i;
int r;
do
{
i = nextIndex(i);
if (table[i] == null)
break;
r = firstIndex(table[i]);
}
while ((i <= r && r < j) || (r < j && j < i)
|| (j < i && i <= r));
table[j] = table[i];
table[j | capacity] = table[i | capacity];
}
while (table[i] != null);
--used;
return obj;
}
}
return null;
}
public Object[] getKeySnap()
{
Object[] tab = table;
int used = this.used;
Object[] res = new Object[used];
for (int i = capacity, j = 0; j < used && i > 0;)
if (tab[--i] != null)
res[j++] = tab[i];
return res;
}
public Object[] getElementSnap()
{
Object[] tab = table;
int used = this.used;
Object[] res = new Object[used];
for (int i = capacity, j = 0; j < used && i < table.length;)
if (tab[i] != null)
res[j++] = tab[i++];
return res;
}
public void clear()
{
int i = capacity;
while (--i >= 0)
table[i] = table[i | capacity] = null;
used = 0;
}
public Enumeration keys()
{
return new Enumerator(table, 0);
}
public Enumeration elements()
{
return new Enumerator(table, capacity);
}
private static class Enumerator
implements Enumeration
{
private final Object[] table;
private final int offset;
private int i;
Enumerator(Object[] table, int offset)
{
this.table = table;
this.offset = offset;
if (table == null)
i = -1;
else
{
i = (table.length >> 1);
skip();
}
}
private final void skip()
{
while (--i >= 0 && table[i] == null)
;
}
public boolean hasMoreElements()
{
return i >= 0;
}
public Object nextElement()
{
if (i < 0)
throw new java.util.NoSuchElementException();
Object result = table[i + offset];
skip();
return result;
}
}
}