Tutorial 07 - james-bern/CS136 GitHub Wiki
Problems
Implement the put and get methods for a hash map.
import java.util.*;
class Tut07HashMap {
// // Little class to store a key-value pair.
// EXAMPLE: KeyValuePair keyValuePair = new KeyValuePair("Bulbasaur", 1);
static class KeyValuePair {
String key;
Integer value;
KeyValuePair(String key, int value) {
this.key = key;
this.value = value;
}
public String toString() {
return key + "=" + value;
}
}
// // The private array of buckets inside the hash map.
private ArrayList<KeyValuePair>[] buckets;
// // Constructor
// NOTE: This looks scary for complicated Java reasons.
@SuppressWarnings("unchecked")
Tut07HashMap() {
// 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<>();
}
}
public String toString() {
return Arrays.toString(buckets);
}
// Put (add, insert) a new key-value pair into the map.
// NOTE: Can also be used to update a key's value.
// NOTE: be sure to compare strings using stringA.equals(stringB),
// NOT the == operator
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;
}
public static void main(String[] arguments) {
Tut07HashMap numberFromName = new Tut07HashMap();
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](/james-bern/CS136/wiki/Venusaur=3,-Charizard=6],-[],-[Charmander=4],-[Ivysaur=2],-[],-[Bulbasaur=1],-[Charmeleon=5)
System.out.println(numberFromName);
// 1, 2, 3, 4, 5, 6, null
System.out.print(numberFromName.get("Bulbasaur") + ", ");
System.out.print(numberFromName.get("Ivysaur") + ", ");
System.out.print(numberFromName.get("Venusaur") + ", ");
System.out.print(numberFromName.get("Charmander") + ", ");
System.out.print(numberFromName.get("Charmeleon") + ", ");
System.out.print(numberFromName.get("Charizard") + ", ");
System.out.println(numberFromName.get("Imakuni?'s Doduo")); // NOTE: Returns null.
}
}
Custom hash functions.
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).
- 🚨 This question is trickier than it sounds! You will need to rehash all the elements, because a key's bucket index
Math.floorMod(key.hashCode(), buckets.length)
is a function of the number of buckets!