Take a moment to introduce yourself to your partner(s). After social pleasantries are complete, pick one member of the team to be the "typer". They'll share their screen while editing the lab code in BlueJ. (I think BlueJ works better for these interactions than Eclipse. It's easier to see when sharing screens, and makes it easier to quickly test individual methods than Eclipse does.) Group members should contribute equally while working through the problems below and discuss all code to be written, though only the "typer" will be able to edit code. Resist the temptation to have both members work simultaneously in BlueJ — you're much more likely to "drift apart" over the course of the lab if you do so. The goal here is to have a partner who's engaged on exactly the same step of the lab as you are.
Experiment
class, and that testing code can be polymorphic because there's an interface (Maplike
) that both map implementations support.
OpenMap
. It's the same basic code we wrote in class, but with a new name and a handful of new methods that will help us with our experiments in a bit. There's a getLoadFactor()
method that is intended to return a value between 0 and 1, indicating the ratio between the number of (key, value) pairs in the map and the size of the array. Modify the appropriate methods in OpenMap
so that the load factor is computed on each put
call, and returned correctly by getLoadFactor
.
OpenMap
class also has methods that are supposed to track and report how many "probes" have been done. The getProbes
and resetProbes
methods are complete, but the returned value won't be correct until you fix up the code a bit. We'll define a probe to be any call to .equals
as we're adding or looking up keys. Modify the get
method so that it counts the number of probes properly. (You can do put
too if you like, but we'll only be worried about counting the probes performed by get
in this lab.)
put
method. I've left the comments that I wrote in my version, but yanked out the actual code.
getLoadFactor
works correctly. Note that for a chaining implementation, this is still the ratio between the number of (key, value) pairs in the map and the size of the array, but that now it could be greater than 1. (If all slots in the array are filled, and each of the lists have a couple of items in them, for example.)
get
method so that it counts the number of probes properly. (You can do put too if you like, but we'll only be worried about counting the probes performed by get
in this lab.)
fillAndTest
in the Experiment
class. It's supposed to take a map instance and a load factor, add random entries to the map until it reaches the desired load factor, then calculate and print the average number of probes required to do a bunch of get
calls. We'll use maps that map strings to strings (both the key and value will be of type String) to keep things simple. You can therefore create random (key, value) pairs by calling my randomString
a couple of times to get a key and value.
When you write the code to test the number of probes, start by resetting the probe counter, then doing at least 1000 get
calls for random keys. After all of the gets, use getProbes()
to see how many total probes were done, and use that to calculate and print an average value.
Experiment
's main method I've left code that creates an OpenMap
and passes it to fillAndTest
. Create a ChainMap
of the same size and pass it to fillAndTest
. See how many probes are required for the maps for a load factor of .75.
fillAndTest
: As you're adding random (key, value) pairs, keep track of the keys you use. (Store them in a list, for example, or a set.) Then, after you've calculated the average number of probes for some retrievals using random keys, do a retrieval for each of the real keys and report that average as well.
fillAndTest
to test this experimentally.
OpenMap
of size 10 and add entries for the following keys, monitoring where they end up after each: ishmael
, whale
, surf
, and harpoon
. Can you figure out where each wanted to go? (You could add a print statement to put()
so it tells you.) How many of them ended up "downstream"? Can get()
still find all of them properly?
main
and have it build a table like the one shown above.
hashCode
function and let you see the impact. Knuth's predictions are based on the assumption that the key's hash function distributes keys evenly across the array, and that might be harder to get right for things other than strings.
hashCode
. See how much luck you have coming up with good hashing functions. (If they don't do a good job of distributing keys across the table, the map performance will suffer.)
remove
methods for one or both of the map classes.