Lab 5: Hashmaps and Exceptions
1 Lab Objectives
To give you practice with Java hashmaps.
To give you practice with Java exceptions and how to write test cases around them.
2 Problem Setup
Many websites recommend books and movies based on combinations of items that other people have liked. For example, if Sue likes "Avatar" and "Driving Miss Daisy" and Joe likes "Avatar", the system might recommend that Joe watch "Driving Miss Daisy". This week, we use this problem as a foundation for practicing with hashtables, exceptions, and Javadoc (Java’s documentation system).
Our goal is to create a recommendation system with two features: (a) for a given user, it can produce a set of items that they like, and (b) given an item, it can produce a set of other items that users who like the given item also like.
3 Design Challenge
Spend a few minutes thinking about the classes and data structures that you would use to create this recommendation system. What data structures do you need to find out what items an individual user likes? What data structures do you need to find out what items users like alongside other items?
Break into discussion groups to review your ideas before you continue.
4 Practice with Hashmaps; Hashmaps containing Lists
Create a Recommender class with a hashmap called Likes that maps names of people to lists of names of items (books, movies, songs, etc). Use Java’s LinkedList class for the list. Use an appropriate access modifier to prevent another class from accessing or editing the hashmap directly.
You may find Java’s hashmap documentation useful for reference.
Add a method addLikes that consumes the name of a person and the name of an item and adds that item to the person’s likes entry.
Add a method likesBoth that consumes the name of a person and the names of two items and returns a boolean indicating whether the person likes both items. If there is no person with the given name in the hashmap, likesBoth should throw an UnknownPersonException to report that no such person was found.
Create an IRecommender interface for the class that requires the addLikes and likesBoth methods.
5 Testing methods that throw Exceptions
Now that our methods can throw exceptions, we need to revise how we write test cases to catch and handle exceptions. To see the issue, create an Examples class with one test case for addLikes and two test cases for likesBoth, one of which tests a person who is in the hashmap and one which tests a person not in the hashmap. Run the tests. What happens on the test that throws the exception?
To handle test cases gracefully in the presence of exceptions, we need to try our former checkExpects and use catch statements to make sure we got the right answers. Here is a sample Examples class that shows how this is done:
class Examples { |
IRecommender r = new Recommender(); |
|
boolean testNoExn (Tester t) { |
try { |
r.addLikes("Gompei", "c"); |
return t.checkExpect(r.likesBoth("Gompei", "c", "d"), false); |
} catch (UnknownPersonException e) { |
return t.checkExpect(false, |
"test threw unexpected exception"); |
} |
} |
|
boolean testGotExn (Tester t) { |
try { |
// note that "Kathi" has not been added to the HashMap |
r.likesBoth("Kathi", "a", "b"); |
return t.checkExpect(false, |
"test failed to throw Exception"); |
} catch (UnknownPersonException e) { |
return t.checkExpect(true, "test threw expected exception"); |
} |
} |
} |
When you use a boolean constant as the first argument to a checkExpect, the tester library will automatically report that test as failing (for false) or passing (for true).
Make sure you understand how this works, and add a test case of your own to get comfortable with the pattern.
6 What to Turn in
Submit all .java files that you produced for this assignment to the Lab5 area via Turnin. You do not need to submit the generated Javadoc files.