package edu.caltech.cs2.datastructures; import edu.caltech.cs2.interfaces.ICollection; import edu.caltech.cs2.interfaces.IDictionary; import java.util.Iterator; import java.util.function.Supplier; public class ChainingHashDictionary implements IDictionary { // chain, supplier //int size, capacity, double load factor (1) //array of dictionary data private Supplier> chain; private IDictionary[] data; private double loadFactor = 1.0; private int size; private int capacity = 17; public ChainingHashDictionary(Supplier> chain) { this.chain = chain; this.data = new IDictionary[capacity]; this.size = 0; for (int i = 0; i < data.length; i++){ this.data[i] = chain.get(); } } /** * @param key * @return value corresponding to key */ @Override public V get(K key) { // V val = this.data[index].get(key); IDictionary chain = this.data[Math.abs((key.hashCode() % capacity + capacity) % capacity)]; if (chain == null || key == null) { return null; } return chain.get(key); } @Override public V remove(K key) { int index = (key.hashCode() % capacity + capacity) % capacity; IDictionary chain = this.data[index]; V val = chain.remove(key); if (val == null) { return null; } else { this.size--; this.data[index] = chain; } return val; } @Override public V put(K key, V value) { if (this.size/this.data.length > this.loadFactor) { rehash(); } V val = null; int index = Math.abs((key.hashCode() % capacity + capacity) % capacity); IDictionary chain = this.data[index]; if (chain == null) { chain = this.chain.get(); } if (chain.get(key) != null) { val = chain.get(key); } else { this.size++; } this.data[index] = chain; chain.put(key, value); return val; } public void rehash(){ //make bigger array //copy items over //this.data = new Arr IDictionary[] arr = new IDictionary[(this.data.length * 2) + 1]; for (IDictionary chain : this.data){ if (chain != null) { for (K key : chain.keys()) { int idx = Math.abs((key.hashCode() % arr.length + arr.length) % arr.length); IDictionary data = arr[idx]; if (data == null) { data = this.chain.get(); } arr[idx] = data; data.put(key, chain.get(key)); } } } this.data = arr; this.capacity = arr.length; } @Override public boolean containsKey(K key) { return (this.get(key) != null); } /** * @param value * @return true if the HashDictionary contains a key-value pair with * this value, and false otherwise */ @Override public boolean containsValue(V value) { return this.values().contains(value); } /** * @return number of key-value pairs in the HashDictionary */ @Override public int size() { return this.size; } @Override public ICollection keys() { ICollection keys = new ArrayDeque<>(); for (IDictionary dict : this.data){ if (dict != null) { for (K key : dict.keys()) { keys.add(key); } } } return keys; } @Override public ICollection values() { ICollection values = new ArrayDeque<>(); for (IDictionary dict: this.data){ if (dict != null) { for (V value : dict.values()) { values.add(value); } } } return values; } /** * @return An iterator for all entries in the HashDictionary */ @Override public Iterator iterator() { return this.keys().iterator(); } }