3.8.4. Tabulka s řetězením synonym
Základem tabulky s řetězením synonym bude pole ukazatelů na první prvek seznamu
synonym. Každá operace začíná výpočtem indexu do tohoto pole - určíme hodnotu
hashCode() klíče a pomocí operace modulo ji převedeme do intervalu indexů pole:
int index = key.hashCode() % table.length;
HashMapEntry entry = table[index];
Dále již následuje v závislosti na konkrétní akci vyhledání položky v seznamu, případně její
odstranění nebo vytvoření nové položky a zařazení na začátek seznamu. Zařazení nové
položky na začátek seznamu je výhodné ze dvou důvodů - jednak je tato operace jednoduchá,
nepotřebujeme si pamatovat ukazatel na předchůdce, jednak je v mnoha aplikacích
pravděpodobné, že budeme dříve hledat ty položky, které jsme vložili naposledy. Výsledné
řešení ukazuje následující příklad.
 | Příklad 3.20. |
|
Vytvořte implementaci tabulky s rozptýlenými položkami využívající řetězení
synonym do jednosměrně vázaného lineárního seznamu.
Konstruktor třídy ChainHashMap má jako parametr počet položek pole, do něhož
se budou ukládat začátky seznamů synonym. Velikost tohoto parametru tedy určuje,
jak rychle se tabulka zaplní a začne docházet k trvalým konfliktům, které zhorší
rychlost vyhledávání i vkládání.
public class ChainHashMap implements Map
{
public ChainHashMap(int capacity)
{
table = new HashMapEntry[capacity];
}
public Object put(Object key, Object value)
{
int index = key.hashCode() % table.length;
HashMapEntry entry = table[index];
while( entry != null ) {
if( key.equals(entry.key) ) {
Object oldValue = entry.value;
entry.value = value;
return oldValue;
}
entry = entry.next;
}
entry = new HashMapEntry();
entry.key = key;
entry.value = value;
entry.next = table[index];
table[index] = entry;
return null;
}
public Object get(Object key)
{
int index = key.hashCode() % table.length;
HashMapEntry entry = table[index];
while( entry != null ) {
if( key.equals(entry.key) )
return entry.value;
entry = entry.next;
}
return null;
}
public Object remove(Object key)
{
int index = key.hashCode() % table.length;
HashMapEntry entry = table[index];
HashMapEntry last = null;
while( entry != null ) {
if( key.equals(entry.key) ) {
if( last == null )
table[index] = entry.next;
else
last.next = entry.next;
return entry.value;
}
last = entry;
entry = entry.next;
}
return null;
}
private static class HashMapEntry {
Object key;
Object value;
HashMapEntry next;
}
HashMapEntry[] table;
}
|
Dalšího vylepšení můžeme dosáhnout například tím, že místo seznamu budeme ze synonym
vytvářet binární vyhledávací strom. Výhodou tabulky s řetězením synonym je zejména to, že
její kapacita není principiálně nijak omezená, i když s přibývajícími položkami v tabulce se
složitost vyhledávání stále více blíží lineární.