/**
 * A hashtable
 **/
public class ChainingArrayHashTable implements HashTable {
	private int size = 100;
	private int entries = 0;
	private Link[] keys = new Link[size];

	public ChainingArrayHashTable() {
	
	}
	/**
 	 * check whether the hashtable is empty
 	 */ 
	public boolean isEmpty() {
		return entries() == 0;
	}

	/**
 	 * check whether the hashtable contains a specific key
 	 */
	public boolean has(Object key) {
		return keys[key.hashCode() % size] != null;
	}
	
	/**
 	 *  get the object associated with a specific key
 	 * @throws java.util.NoSuchElementException
 	 * 	if the specified key is not in the hashtable
 	 */ 
	public Object get(Object key) {
		int a = key.hashCode() % size; 
		if (keys[a] == null)
			throw new java.util.NoSuchElementException();
		else {
			Link obj = keys[a];
			while (obj != null)
				if (obj.getKey().equals(key))
					return obj.getValue();
				else
					obj = obj.next;
				
			throw new java.util.NoSuchElementException();
		}
	}
	
	/**
 	 *  remove the object associated with a specific key
 	 * @throws java.util.NoSuchElementException
 	 * 	if the specified key is not in the hashtable
 	 */ 
	public Object remove(Object key) {
		Object obj = get(key);
		put(key, null);
		entries--;
		return obj;
	}
	
	/**
 	 * Add `key' to the hashtable and associate it with `value'
 	 */
	public void put(Object key, Object value) {
		int a = key.hashCode() % size; 
		if (keys[a] == null) {
			keys[a] = new Link(key, value, keys[a]);
			entries++;
		}	
		else {
			Link obj = keys[a];
			while (obj != null)
				if (obj.getKey().equals(key)) {
					obj.setValue(value);
					return;
				}
				else
					obj = obj.next;
			keys[a] = new Link(key, value, keys[a]);
			entries++;
		}
	}

	
	/**
 	 * Return the number of keys in the hashtable
 	 */ 
	public int entries() {
		return entries;
	}
	
	/**
 	 * Return the keys in the hashtable
 	 */ 
	public Object[] keys() {
		return keys;
	}
}
