/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package java.util;
public class Hashtable extends Object
{
private static class Entry extends Object
{
public int hash;
public Object key;
public Object value;
public Entry next;
Entry(int hash, Object key, Object value, Entry next)
{
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}
private static class Enumerator extends Object
implements Enumeration
{
private boolean keys;
private int index;
private Entry[] table;
private Entry entry;
Enumerator(boolean keys, Entry[] table)
{
this.keys = keys;
this.index = table.length;
this.table = table;
this.entry = null;
}
public boolean hasMoreElements()
{
int i;
Entry[] t;
if(entry != null)
{
return true;
}
for(t = table, i = index; i-- > 0; )
{
if((entry = t[i]) != null)
{
index = i;
return true;
}
}
index = i;
return false;
}
public Object nextElement()
{
int i;
Entry[] t;
Entry e;
if(entry == null)
{
for(t = table, i = index; i-- > 0 && (entry = t[i]) == null; );
index = i;
}
if((e = entry) == null)
{
throw new NoSuchElementException("Hashtable: " +
"больше не осталось элементов для перечисления.");
}
entry = e.next;
return keys ? e.key : e.value;
}
}
private int factor;
private int length;
private Entry[] table;
private Object lock;
public Hashtable()
{
this(15);
}
public Hashtable(int initialCapacity)
{
if(initialCapacity < 0)
{
throw new IllegalArgumentException("Hashtable: " +
"параметр initialCapacity не может быть отрицательным.");
}
if(initialCapacity == 0)
{
initialCapacity = 1;
}
this.factor = (initialCapacity * 3) / 4;
this.table = new Entry[initialCapacity];
this.lock = new Object();
}
public String toString()
{
int i;
Entry[] t;
Enumerator k;
Enumerator e;
StringBuffer result = new StringBuffer('{');
synchronized(lock)
{
t = table;
k = new Enumerator(true, t);
e = new Enumerator(false, t);
for(i = length; i-- > 0; )
{
result.append(k.nextElement().toString()).append('=').
append(e.nextElement().toString());
if(i > 0)
{
result.append(", ");
}
}
}
return result.append('}').toString();
}
public void clear()
{
int i;
Entry[] t;
synchronized(lock)
{
for(i = (t = table).length; i-- > 0; t[i] = null);
length = 0;
}
}
public boolean isEmpty()
{
return length == 0;
}
public boolean contains(Object value)
{
boolean result;
int i;
Entry[] t;
Entry e;
if(value == null)
{
throw new NullPointerException("Hashtable.contains: " +
"параметр value равен нулевой ссылке.");
}
synchronized(lock)
{
label0:
{
for(i = (t = table).length; i-- > 0; )
{
for(e = t[i]; e != null; e = e.next)
{
if(!value.equals(e.value))
{
continue;
}
result = true;
break label0;
}
}
result = false;
}
}
return result;
}
public boolean containsKey(Object key)
{
boolean result;
int hash;
Entry[] t;
Entry e;
if(key == null)
{
throw new NullPointerException("Hashtable.containsKey: " +
"параметр key равен нулевой ссылке.");
}
synchronized(lock)
{
label0:
{
e = (t = table)[((hash = key.hashCode()) & Integer.MAX_VALUE) % t.length];
for(; e != null; e = e.next)
{
if(hash != e.hash || !key.equals(e.key))
{
continue;
}
result = true;
break label0;
}
result = false;
}
}
return result;
}
public int size()
{
return length;
}
public Object remove(Object key)
{
int i;
int hash;
Entry[] t;
Entry e;
Entry f;
Object result;
if(key == null)
{
throw new NullPointerException("Hashtable.remove: " +
"параметр key равен нулевой ссылке.");
}
synchronized(lock)
{
label0:
{
f = null;
e = (t = table)[i = ((hash = key.hashCode()) & Integer.MAX_VALUE) % t.length];
for(; e != null; f = e, e = e.next)
{
if(hash != e.hash || !key.equals(e.key))
{
continue;
}
if(f != null)
{
f.next = e.next;
} else
{
t[i] = e.next;
}
length--;
result = e.value;
break label0;
}
result = null;
}
}
return result;
}
public Object get(Object key)
{
int hash;
Entry[] t;
Entry e;
Object result;
if(key == null)
{
throw new NullPointerException("Hashtable.get: " +
"параметр key равен нулевой ссылке.");
}
synchronized(lock)
{
label0:
{
e = (t = table)[((hash = key.hashCode()) & Integer.MAX_VALUE) % t.length];
for(; e != null; e = e.next)
{
if(hash != e.hash || !key.equals(e.key))
{
continue;
}
result = e.value;
break label0;
}
result = null;
}
}
return result;
}
public Object put(Object key, Object value)
{
int i;
int l;
int hash;
Entry[] t;
Entry e;
Object result;
if(key == null)
{
throw new NullPointerException("Hashtable.put: " +
"параметр key равен нулевой ссылке.");
}
if(value == null)
{
throw new NullPointerException("Hashtable.put: " +
"параметр value равен нулевой ссылке.");
}
synchronized(lock)
{
label0:
{
e = (t = table)[i = ((hash = key.hashCode()) & Integer.MAX_VALUE) % t.length];
for(; e != null; e = e.next)
{
if(hash != e.hash || !key.equals(e.key))
{
continue;
}
result = e.value;
e.value = value;
break label0;
}
if((l = length) >= factor)
{
rehash();
i = (hash & Integer.MAX_VALUE) % (t = table).length;
}
t[i] = new Entry(hash, key, value, t[i]);
length = l + 1;
result = null;
}
}
return result;
}
public Enumeration keys()
{
return new Enumerator(true, table);
}
public Enumeration elements()
{
return new Enumerator(false, table);
}
protected void rehash()
{
int i;
int j;
int nc;
int oc;
Entry[] nt;
Entry[] ot;
Entry e;
Entry f;
table = nt = new Entry[nc = ((oc = (ot = table).length) << 1) + 1];
factor = (nc * 3) / 4;
for(i = oc; i-- > 0; )
{
for(f = ot[i]; f != null; )
{
j = ((e = f).hash & Integer.MAX_VALUE) % nc;
f = f.next;
e.next = nt[j];
nt[j] = e;
}
}
}
}