Tut07 - james-bern/CS136 GitHub Wiki

TODO's

  • A
    • Implement put
    • Implement get
  • A+
    • Use your own custom hash function instead of the build in object.hashCode() and compare how many collisions you get. Can you design a really good hash function for this problem? Can you design a really bad one?
    • resize(): Once a hash map gets too full, it stops being as fast. This is because we waste a bunch of time looking through array lists. Load factor is the technical term for how full a hash map is. Add a method called resize() that doubles the number of buckets. Automatically call this function inside of put(...) if the load factor is high enough (NOTE: you may want to add an instance variable int size; that tells you how many elements are currently stored in the hash map).
      • You will need to rehash all the elements, because a key's bucket index MODULO(key.hashCode(), buckets.length) is a function of the number of buckets!

Starter Code

import java.util.*;
class Tut07 extends Cow {

	// // Little class to store a key-value pair.
	// NOTE: Assumes String key and Integer value.
	static class KeyValuePair {
		String key;
		Integer value; // NOTE: Using Integer for consistency because map.get(...) can return null

		// // Constructor
		// EXAMPLE: KeyValuePair pair = new KeyValuePair("Bulbasaur", 1);
		KeyValuePair(String key, Integer value) {
			this.key = key;
			this.value = value;
		}

		// toString (called by PRINT)
		public String toString() { return key + "=" + value; }
	}

	static class XHashMap {

		// // The private array of buckets inside the hash map.
		// NOTE: This is an array of array lists of key-value pairs
		private ArrayList<KeyValuePair>[] buckets;

		// // Put (add, insert) a new key-value pair into the map.
		// NOTE: Can also be used to update a key's value.
		// NOTE: Compare strings using stringA.equals(stringB), NOT ==
		void put(String key, Integer value) {
			// TODO
		}

		// // Get (lookup) a key's value in the map.
		// NOTE: Return null if map doesn't contain key.
		Integer get(String key) {
			// TODO
			return null;
		}


		// // Constructor
		// NOTE: This looks scary for complicated Java reasons.
		@SuppressWarnings("unchecked")
		XHashMap() {
			// Create a new buckets array 
			buckets = (ArrayList<KeyValuePair>[]) new ArrayList[7];
			// Iterate through the array and create a new (empty) bucket in each slot  
			for (int i = 0; i < buckets.length; ++i) {
				buckets[i] = new ArrayList<>();
			}
		}

		// // toString (called by PRINT)
		public String toString() { return Arrays.toString(buckets); }
	}

	public static void main(String[] arguments) {
		XHashMap numberFromName = new XHashMap();
		numberFromName.put("Bulbasaur",  1);
		numberFromName.put("Ivysaur",    2);
		numberFromName.put("Venusaur",   3);
		numberFromName.put("Charmander", 4);
		numberFromName.put("Charmeleon", 5);
		numberFromName.put("Charizard", 42);
		numberFromName.put("Charizard",  6); // NOTE: Overwrites 42 with 6.

		// [[Venusaur=3, Charizard=6], [], [Charmander=4], [Ivysaur=2], [], [Bulbasaur=1], [Charmeleon=5]]
		PRINT(numberFromName);

		PRINT();
		PRINT("Bulbasaur        -> " + numberFromName.get("Bulbasaur"       ));
		PRINT("Ivysaur          -> " + numberFromName.get("Ivysaur"         ));
		PRINT("Venusaur         -> " + numberFromName.get("Venusaur"        ));
		PRINT("Charmander       -> " + numberFromName.get("Charmander"      ));
		PRINT("Charmeleon       -> " + numberFromName.get("Charmeleon"      ));
		PRINT("Charizard        -> " + numberFromName.get("Charizard"       ));
		PRINT("Imakuni?'s Doduo -> " + numberFromName.get("Imakuni?'s Doduo")); // NOTE: Returns null.
	}
} 

Solution

👀 ```java import java.util.*; class Tut07 extends Cow {
// // Little class to store a key-value pair.
// NOTE: Assumes String key and Integer value.
static class KeyValuePair {
	String key;
	Integer value; // NOTE: Using Integer for consistency because map.get(...) can return null

	// // Constructor
	// EXAMPLE: KeyValuePair pair = new KeyValuePair("Bulbasaur", 1);
	KeyValuePair(String key, Integer value) {
		this.key = key;
		this.value = value;
	}

	// toString (called by PRINT)
	public String toString() { return key + "=" + value; }
}

static class XHashMap {

	// // The private array of buckets inside the hash map.
	// NOTE: This is an array of array lists of key-value pairs
	private ArrayList<KeyValuePair>[] buckets;

	// // Put (add, insert) a new key-value pair into the map.
	// NOTE: Can also be used to update a key's value.
	// NOTE: Compare strings using stringA.equals(stringB), NOT ==
	void put(String key, Integer value) {
		int bucketIndex = MODULO(key.hashCode(), buckets.length);
		ArrayList<KeyValuePair> bucket = buckets[bucketIndex];
		for (int i = 0; i < bucket.size(); ++i) {
			KeyValuePair pair = bucket.get(i);
			if (pair.key.equals(key)) {
				pair.value = value;
				return;
			}
		}
		bucket.add(new KeyValuePair(key, value));
	}

	// // Get (lookup) a key's value in the map.
	// NOTE: Return null if map doesn't contain key.
	Integer get(String key) {
		int bucketIndex = MODULO(key.hashCode(), buckets.length);
		ArrayList<KeyValuePair> bucket = buckets[bucketIndex];
		for (int i = 0; i < bucket.size(); ++i) {
			KeyValuePair pair = bucket.get(i);
			if (pair.key.equals(key)) {
				return pair.value;
			}
		}
		return null;
	}


	// // Constructor
	// NOTE: This looks scary for complicated Java reasons.
	@SuppressWarnings("unchecked")
	XHashMap() {
		// Create a new buckets array 
		buckets = (ArrayList<KeyValuePair>[]) new ArrayList[7];
		// Iterate through the array and create a new (empty) bucket in each slot  
		for (int i = 0; i < buckets.length; ++i) {
			buckets[i] = new ArrayList<>();
		}
	}

	// // toString (called by PRINT)
	public String toString() { return Arrays.toString(buckets); }
}

public static void main(String[] arguments) {
	XHashMap numberFromName = new XHashMap();
	numberFromName.put("Bulbasaur",  1);
	numberFromName.put("Ivysaur",    2);
	numberFromName.put("Venusaur",   3);
	numberFromName.put("Charmander", 4);
	numberFromName.put("Charmeleon", 5);
	numberFromName.put("Charizard", 42);
	numberFromName.put("Charizard",  6); // NOTE: Overwrites 42 with 6.

	// [[Venusaur=3, Charizard=6], [], [Charmander=4], [Ivysaur=2], [], [Bulbasaur=1], [Charmeleon=5]]
	PRINT(numberFromName);

	PRINT();
	PRINT("Bulbasaur        -> " + numberFromName.get("Bulbasaur"       ));
	PRINT("Ivysaur          -> " + numberFromName.get("Ivysaur"         ));
	PRINT("Venusaur         -> " + numberFromName.get("Venusaur"        ));
	PRINT("Charmander       -> " + numberFromName.get("Charmander"      ));
	PRINT("Charmeleon       -> " + numberFromName.get("Charmeleon"      ));
	PRINT("Charizard        -> " + numberFromName.get("Charizard"       ));
	PRINT("Imakuni?'s Doduo -> " + numberFromName.get("Imakuni?'s Doduo")); // NOTE: Returns null.
}

}

</details>
⚠️ **GitHub.com Fallback** ⚠️