Lab 06: A Set Collection Due: date-time
Lab 06: A Set Collection
Learning Objectives
- Explore another collection interface.
- Develop a Java 5 generic implementation for a collection.
- Work with raw arrays for internally representing a collection.
- Develop test cases for collection methods.
Overview
In this lab you will complete the implementation of a collection called a set. After examining its interface, you will complete an implementation that uses formal Java 5 generics. In lab last week, you used an ArrayList
object as the underlying implementation mechanism for the bag collection. This week, you'll implement a set using an actual array.
Part I: A Set Collection
A set is a collection of objects that contains no duplicates. Adding an element to a set has no effect if an equal element is already contained in the set. Like the bag collection from last week's lab, a set has no inherent order, so there is no notion of position.
First, determine with your partner who will initially play the roles of driver and navigator. Review the principles of pair programming if necessary.
Download and unzip the files provided for this lab (lab06files.zip). Create a new project for this lab in Eclipse and add all files to its source directory. Don't forget to include CS2114-Support.
The file
Set.java
contains an interface that describes a set collection. This is a subset of thejava.util.Set
interface defined in the Java API (thejava.util.Set
interface is a bit too long to implement in lab). Do not make changes to this interface.Discuss the interface methods with your partner, noting the use of the parameterized type
Item
.Note also the
@precondition
and@postcondition
tags in the javadoc comments. A collection could be defined so that it allows null elements. In this case, null elements are not allowed.
The
ArraySet.java
file contains a partial implementation of theArraySet
class, which implements theSet
interface. Your task is to complete this class. Create exhaustive test cases for each method ofArraySet
AS YOU GO. AnArraySetTest
class has been provided for you as a starting point, but note that most of its tests are not yet written, and in many cases, you will want to have multiple test cases for eachArraySet
method to check all possible behaviors. Don't wait until you've completed the implementation to perform unit testing. For this lab, it is sufficient to useString
objects as elements of the set in your tests.Examine the implementation of the
ArraySet
constructor, which uses an initial capacity of 10 (using the declared constant, of course). Remember (from the implementation of theKWArrayList
class) that you can't instantiate an array of the generic type -- you have to create an array ofObject
and cast it into an array of the generic type. Examine carefully how it creates the array.You have been given the implementations of
size()
,isEmpty()
, andtoString()
, and you have also been given corresponding test cases for them (of course, the tests won't pass until you implementadd()
, later). Briefly examine these methods so that you understand how they work, and then move on to the next step.By thinking carefully for a moment about the
add()
,remove()
, andcontains()
methods for a set, you can find common behavior and improve the design of your implementation. You only add a new element if it isn't already in the set. And to remove an element, you first must find it. Thecontains()
method is used to determine if an element is in the set, returning a boolean result. So whileadd()
could make use ofcontains()
, bothcontains()
andremove()
could benefit from a private helper method that returns the index of the found element.Write test cases for the
contains()
method (some test cases might useadd()
, so they may not pass until you have implemented it as well--but not every test forcontains()
should requireadd()
). Write a private helper method that takes an item and returns its index in the array, or -1 if it was not found. Then complete the implementation of thecontains()
method.Now write test cases for the
add()
method. Remember, do not attempt to write test cases that violate a method's preconditions.Complete the implementation of the
add()
method, which first asserts the precondition, then checks to see if the capacity of the array has been reached and expands it if necessary. Be sure to run the test cases you have, to make sure that your work so far behaves as you expect. And note that since there is no concept of position, you can always add a new element to the next empty position in your array.The
expandCapacity()
private helper method doesn't really change the capacity of an existing array (you can't change the size of an array once it is created). Instead, it creates a new array twice as big as the old one, then copies over the existing contents to the new array. Complete this method. Note that you won't write test cases for it directly, since it is private--instead, it will be tested by your test cases foradd()
. Note thatexpandCapacity()
won't be covered unless you write a test case that causes the set to fill up beyond its capacity; use theset2
variable given in the test class that has an initial capacity of 1 to make testing this easier.
Part II: Finishing the Set Implementation
Switch roles with your partner at this point. The driver will now be the navigator and vice versa. As always, respect these roles.
Now implement the
clear()
and write the corresponding test for it. When implementingclear()
, avoid the temptation to write a loop or callremove()
--think of a simpler, faster way (discuss with your partner on how to do this, or ask for help if neither of you can think of a way).Submit your code to Web-CAT. Fix any problems, and resubmit as necessary. Maximize your score now.
Write test cases for the
remove()
method and then complete its implementation. When you remove an item from the set, you don't want to leave a "hole" in the array where the removed item was. Instead, you need to shift the items after the one that was removed back one position. Think carefully about how you would write a for-loop to do this -- be cautious of off-by-one errors. Page 75 of the textbook has an example of this in their implementation ofremove()
for theKWArrayList
.Write test cases for the
equals()
method and then complete its implementation. Remember that thisequals()
method determines if one set is equal to another. Two sets are equal if they contain the same elements. But the elements need not be in the same order in the arrays of the two sets. So to determine if two sets are equal, see if each element in one set is contained in the other, and that there are no "extra" elements in either set (that both sets are the same size).Write test cases for the
removeAny()
method and then complete its implementation. Note that, unlike last week, this implementation is not set up to select an item at random to remove. Instead, since clients of this class cannot count on any particular item being removed, we can select any one. Why not pick the item that is easiest to remove? Think of which is easiest, and use that choice in implementingremoveAny()
(here's a hint: the easiest element to remove can be removed without modifying the contents of the array at all). Also, avoid callingremove()
withinremoveAny()
(if you're not sure why, discuss it with your partner).
Part III: Final Submission to Web-CAT
Continue to submit your code to Web-CAT.
Examine the results, fix any problems, and resubmit as necessary.
Each partner should keep a local copy of the submission.