This assignment is meant to build your skill in manipulating arrays and in developing if statements and while loops.
You should be familiar with the notion of a set, which is just a collection of items. For example, { 2, 3, 5, 7 } is the set of prime numbers less than ten. With respect to a set, a value either is or is not a member.
The bag concept generalizes the concept of set. With respect to a bag, the question is not simply whether a given value is, or is not, a member, but rather how many times it occurs in the bag. This is called the value's multiplicity. For example, in the bag {: 2, 2, 2, 5, 5, 11 :} (which we could just as well express as {: 5, 2, 2, 11, 2, 5 :}, as the order in which members are listed is irrelevant) there are three occurrences of 2, two occurrences of 5, one occurrence of 11, and zero occurrences of every other value. (One possible interpretation is that this bag represents the prime factorization of 2200 = 23 × 52 × 11.)
Your task is to complete the development of a class, BagOfStrings, instances of which represent —surprise!—bags of strings. The hyperlink in the previous sentence leads to a partially-completed version of that class.
All the instance variables you need are already declared, two constructors are given in full, and so are three public methods (resetIter(), hasNext(), and next()) that provide "iterator" functionality, as discussed in lecture. The private method resizeArrays() is also given in full.
Also provided are the signatures/headings of the remaining public methods (plus the private (and crucial) method indexOf), as well as detailed comments describing their intended behaviors. However, their bodies have been left as "stubs" (for you to fill in).
Aside from the iterator-related methods, the remaining mutators are for either adding or removing instances of strings from the bag. The observers are for reporting such information as the size of the bag or whether or not a given string is a member of the bag (or, more precisely, a given string's multiplicity (i.e., number of occurrences)).
To give you an idea of how your code should work, suppose that we had an instance bs of BagOfStrings representing the bag
having four occurrences of "is", two occurrences of "cat", and one occurrence of each of "run", "the", and "$e#". One possible state of bs (ignoring the instance variable iteratorLoc) is as follows:
members multiplicities numDistinctMembers
+-------+ +-----+ +-----+
0 | "cat" | 0 | 2 | | 5 |
+-------+ +-----+ +-----+
1 | "run" | 1 | 1 |
+-------+ +-----+
2 | "$e#" | 2 | 1 | size
+-------+ +-----+ +-----+
3 | "is" | 3 | 4 | | 9 |
+-------+ +-----+ +-----+
4 | "the" | 4 | 1 |
+-------+ +-----+
5 | dc | 5 | dc |
+-------+ +-----+
6 | dc | 6 | dc |
+-------+ +-----+
. .
. .
. .
Notice that, if a string is stored in members[i], its multiplicity is stored in the corresponding element of multiplicities[]. The symbol dc means don't care, suggesting that the value there is irrelevant.
Suppose that (via a call to addOccurrence()) an occurrence of "is" is to be added to bs. Then, because "is" can be found at members[3] (a fact that should be ascertainable via a call to indexOf()), the appropriate modifications to bs's instance variables are to
Suppose now that (via a call to addOccurrences()) four occurrences of "gorn" are to be added to bs. Since "gorn" is not a member of bs (which, again, should be ascertainable via a call to indexOf()), the appropriate modifications are to
What should happen if a new member is added to a bag, but there are no "empty" array elements in which to record the relevant data? (This corresponds to the situation in which numDistinctMembers = members.length.) This is when the resizeArrays() method (provided for you) should be called in order to increase the lengths of the arrays members[] and multiplicities[]. Having done that, you can then record the necessary data regarding the new bag member. (Note that, technically, the arrays are not being "re-sized", but rather new, longer arrays are being created and data from the old ones are being copied into the new ones.) By how much should the lengths of the arrays be increased? A good rule of thumb in a situation like this is to double their lengths.
If one or more occurrences of a bag member are removed (via a call to one of the relevant methods), the appropriate element of multiplicities[] should be modified, of course, as should size. But what happens in the case that a member's multiplicity goes to zero? For example, suppose that the lone occurrence of "run" is removed from bs. We could (in addition to updating size) just change multiplicities[1] to zero and leave it at that. Following this approach, however, would mean that any string that was ever a member of the bag would be stored in members[], as opposed to only those strings that currently are members. Perhaps a better approach would be to remove "run" from members[]. How? We could shift the values in the succeeding elements of the arrays up by one position. But that would be silly, given that we don't care about the ordering of the strings in members[]. A much better idea is to copy the values from the last "meaningful" location in the arrays into the location being "vacated" by the removed string. In this particular case, that would mean putting "the" and 1, respectively, into members[1] and multiplicities[1], and decrementing numDistinctMembers.
As noted earlier, the indexOf() method will be crucial to your class. Its responsibility (as noted in the comments that accompany it) is, given a string str, to find the smallest value k such that either k == numDistinctMembers or members[k].equals(str). It is vital that, when comparing two String objects to determine whether they represent the same sequence of characters, you use the String class's equals() method (as in the previous sentence), as opposed to using the == operator. We shall discuss this in class.
To test your work, you can use the BagOfStringsTester class. If you invoke this class's main() method, you can then enter commands via the keyboard to be applied to a BagOfStrings object. (The main() method is static, so (in BlueJ) right click on the class icon to get to it, rather than creating an object of that class.) The list of available commands appears in the comments near the beginning of the class's source code. The same list appears if you enter the command help when running the application.
Remember to properly format your code, and do not have any line go beyond 80 characters. Violations of either of these rules will lead to penalties.
When you're ready, use the Submit/Review link for this assignment on the course web page in order to submit your work for grading. (If, subsequent to making a submission, you make significant improvements to your work (e.g., by correcting one or more logic errors), you are encouraged to submit again.) If you make a submission after the due date, especially if it is not your first submission, please inform your instructor by e-mail. The file you are to submit is BagOfStrings.java (as opposed to BagOfStrings.class).
The message area of the submission page is available for you to convey any brief comment or observation that you think is worthwhile. (For example, here you might point out any incorrect behaviors you have observed being exhibited by objects of the class(es) that you're submitting.)