import lrs.*;
import listFW.*;
/**
* An IDictionary implemented using a hash table. Collisions
are handled
* using chaining. The chains are implemented using
DictLRS (code shown below).
*
* Uses the method hashCode() defined by class Object as the
hash
* function. Any class may override this method with
a new
* implementation.
*
* @author Alan L. Cox
* @since 04/01/02
* @since 11/17/02 - Modified by DXN
*/
public class DictHash implements IDictionary {
/*
* Initialize _table to reference a single-element
array of
* IDictionary, containing in its single
element a reference to an
* empty DictLRS.
*/
private IDictionary[] _table = { new DictLRS()
};
private int _tableOccupancy = 0;
private double _loadFactor;
public DictHash(double loadFactor) {
_loadFactor = loadFactor;
}
/*
* An IList factory used by elements()
*/
private IListFactory _lf = new CompositeListFactory();
/**
* Clears the contents of the dictionary
leaving it empty.
*
* Implemented by replacing the existing
LRStruct with a new,
* empty one.
*/
public void clear() {
_table = new DictLRS[1];
_table[0] = new DictLRS();
_tableOccupancy = 0;
}
/**
* Returns true if the dictionary is empty
and false otherwise.
*/
public boolean isEmpty() {
return _tableOccupancy
== 0;
}
/**
* Returns an IList of DictionaryPairs
corresponding to the entire
* contents of the dictionary.
*
* Note that the elements are not in order.
*/
public IList elements() {
IList l = _lf.makeEmptyList();
for (int i = 0; i <
_table.length; i++)
l = (IList)_table[i].elements().execute(new IListAlgo() {
public Object emptyCase(IList host, Object input) {
return input;
}
public Object nonEmptyCase(IList host, Object input) {
return _lf.makeNEList(host.getFirst(),
(IList)host.getRest().execute(this,
input));
}
}, l);
return l;
}
/**
* Returns the DictionaryPair with the
given key. If there is not
* a DictionaryPair with the given key,
returns null.
*
* Returns a DictionaryPair rather than
the value alone so that
* the user can distinguish between not
finding the key and
* finding the pair (key, null).
*
* This method is O(1) in the expected
case and O(n) in the worst
* case.
*
* @param key the key to lookup
* @return the DictionaryPair found
*/
public DictionaryPair lookup(Comparable key)
{
int index = key.hashCode()
% _table.length;
return _table[index].lookup(key);
}
/**
* Inserts the given key and value.
If the given key is already
* in the dictionary, the given value replaces
the key's old
* value.
*
* This method is O(1) in both the expected
case and the worst
* case if we amortize the cost of doubling
the hash table over
* subsequent insert()'s.
*
* @param key the key to insert
* @param value the value to insert
*/
public void insert(Comparable key, Object value)
{
if (_tableOccupancy
>= (_loadFactor * _table.length)) {
int i;
final IDictionary newTable[] = new IDictionary[2*_table.length];
for (i = 0; i < newTable.length; i++)
newTable[i] = new DictLRS();
for (i = 0; i < _table.length; i++) {
_table[i].elements().execute(new IListAlgo() {
public Object emptyCase(IList host, Object input) {
return null;
}
public Object nonEmptyCase(IList host, Object input) {
DictionaryPair pair = (DictionaryPair) host.getFirst();
int index = pair.getKey().hashCode() % newTable.length;
newTable[index].insert(pair.getKey(), pair.getValue());
return host.getRest().execute(this, input);
}
}, null);
}
_table = newTable;
}
int index = key.hashCode()
% _table.length;
_tableOccupancy++;
_table[index].insert(key,
value);
}
/**
* Removes the DictionaryPair with the
given key and returns it.
* If there is not a DictionaryPair with
the given key, returns
* null.
*
* This method is O(1) in the expected
case and O(n) in the worst
* case.
*
* @param key the key to remove
* @return the DictionaryPair removed
*/
public DictionaryPair remove(Comparable key)
{
int index = key.hashCode()
% _table.length;
DictionaryPair pair = _table[index].remove(key);
if (pair != null)
_tableOccupancy--;
return pair;
}
/**
* Returns a string representing the contents
of the dictionary.
*/
public String toString() {
return elements().toString();
}
}
package dict;
import java.lang.*;
import lrs.*;
import listFW.*;
/**
* An implementation of IDictionary using an LRStruct to hold the
* DictionaryPairs.
*/
public class DictLRS implements IDictionary {
/*
* A list of DictionaryPairs ordered by key
*/
private LRStruct _lrs = new LRStruct();
/**
* Clears the contents of the dictionary leaving it empty.
*
* Implemented by replacing the existing LRStruct with a new,
* empty one.
*/
public void clear() {
_lrs = new LRStruct();
}
/**
* Returns true if the dictionary is empty and false otherwise.
*
* Implemented as a visitor to LRStruct.
*/
public boolean isEmpty() {
return ((Boolean)_lrs.execute(new IAlgo() {
public Object emptyCase(LRStruct host, Object input) {
return Boolean.TRUE;
}
public Object nonEmptyCase(LRStruct host, Object input) {
return Boolean.FALSE;
}
}, null)).booleanValue();
}
/**
* Returns an IList of DictionaryPairs corresponding to the entire
* contents of the dictionary.
*
* Implemented as a visitor to LRStruct.
*/
public IList elements() {
return (IList)_lrs.execute(new IAlgo() {
IListFactory lf = new CompositeListFactory();
public Object emptyCase(LRStruct host, Object input) {
return lf.makeEmptyList();
}
public Object nonEmptyCase(LRStruct host, Object input) {
return lf.makeNEList(host.getFirst(),
(IList)host.getRest().execute(this, input));
}
}, null);
}
/**
* Returns the DictionaryPair with the given key. If there is not
* a DictionaryPair with the given key, returns null.
*
* Returns a DictionaryPair rather than the value alone so that
* the user can distinguish between not finding the key and
* finding the pair (key, null).
*
* Implemented as a visitor to LRStruct.
*/
public DictionaryPair lookup(Comparable key) {
return (DictionaryPair)_lrs.execute(new IAlgo() {
public Object emptyCase(LRStruct host, Object input) {
return null;
}
public Object nonEmptyCase(LRStruct host, Object input) {
DictionaryPair first = (DictionaryPair)host.getFirst();
int result = first.getKey().compareTo(input);
if (result > 0) // host > input
return null;
else if (result == 0) // host == input
return first;
else // host < input
return host.getRest().execute(this, input);
}
}, key);
}
/**
* Inserts the given key and value. If the given key is already
* in the dictionary, the given value replaces the key's old
* value.
*
* Implemented as a visitor to LRStruct that inserts the key and
* value in order.
*/
public void insert(Comparable key, Object value) {
_lrs.execute(new IAlgo() {
public Object emptyCase(LRStruct host, Object input) {
return host.insertFront(input);
}
public Object nonEmptyCase(LRStruct host, Object input) {
DictionaryPair first = (DictionaryPair)host.getFirst();
int result = first.compareTo(input);
if (result > 0) // host > input
return host.insertFront(input);
else if (result == 0) // host == input
return host.setFirst(input);
else // host < input
return host.getRest().execute(this, input);
}
}, new DictionaryPair(key, value));
}
/**
* Removes the DictionaryPair with the given key and returns it.
* If there is not a DictionaryPair with the given key, returns
* null.
*
* Implemented as a visitor to LRStruct.
*/
public DictionaryPair remove(Comparable key) {
return (DictionaryPair)_lrs.execute(new IAlgo() {
public Object emptyCase(LRStruct host, Object input) {
return null;
}
public Object nonEmptyCase(LRStruct host, Object input) {
DictionaryPair first = (DictionaryPair)host.getFirst();
int result = first.getKey().compareTo(input);
if (result > 0) // host > input
return null;
else if (result == 0) { // host == input
host.removeFront();
return first;
} else // host < input
return host.getRest().execute(this, input);
}
}, key);
}
/**
* Delegates the conversion to the LRStruct toString().
*/
public String toString() {
return _lrs.toString();
}
}