CSCI 235 Lab 14: More Java Collections

Before proceeding, finish up the collections portion of the previous lab and be sure that you have handed it in.

This lab continues working with classes from the Java Collections framework (ArrayList, HashMap, HashSet, and Iterator), along with introducing the StringTokenizer class. You’ll be creating a new version of the program that you wrote for the last lab, working in the counter subdirectory.

1. Review

In the code from the last lab, note how you did the following things:

Make sure you understand what you had to do for each of these things.

Also make sure that all of your changes are committed to your Mercurial repository.

2. The for-each loop

Copy the FileProcessor.java code to make a new class FileProcessor2. To do that, first use hg copy to copy it to a new file, then edit that file and change its class name to match the file name.

In the previous lab, you stepped through collections by explicitly creating an instance of Iterator and calling its hasNext() and next methods. That pattern of access is common enough that Java provides a special version of the for statement to do it. For any iterable collection coll with an element type T, you can write a loop as

    for (T x: coll) 
        process element x
    

Because the body is executed for each element in the collection, this is usually called a for-each loop. Note that coll has to be something that has a method iterator().

Rewrite each of your for loops that processes a collection to use a for-each loop. (You need to be careful with your HashMap, because you can’t iterate over the map itself.)

Test your new program and commit it to the repository.

3. Processing the file input

You were provided with a class FileAux with a method fileToWords() to do the initial processing of the file input. You are now going to write your own method to do that, using the file input classes that were introduced yesterday.

Create a file FileWords.java that includes a declaration of a static method fileToWords() that will be able to take the place of the one that was provided to you. You can figure out its parameter types and return type from where it will be called in FileProcessor2.

Tell Mercurial about this new file:

$ hg add FileWords.java

Now you need to fill in your new method. It needs to open the named file and make a Scanner for it, then read and process each line from the file. The processing for each line involves splitting it into words and adding each of those words to the ArrayList that will be returned.

It probably makes sense to write this and test it in stages. You can do the testing by writing a main() method in the new class. I’d suggest first getting the file opened and read (and print) each line from it. Then go back and set up the list, add each line to it, and print the entire list at the end. Then worry about the inner loop that does the breaking a line into words.

Tips:

Once you have that working, commit it to your repository. Fix the call at the beginning of main() to call your method instead of the one that was provided.

4. Extra credit

If you think about how the apostrophe (single quote) is used in English, it is not always correct to use it to split words: we should treat contractions (such as ”don’t”) and possessives (such as ”God’s”) as single words. The method you were orginally provided does that, but the one you have written does not.

To fix that behavior, you need to take the single-quote out of the set of delimiters. But then it behaves oddly when used as a quotation mark. So the answer is to not treat it as a delimiter, but to put in an explicit test that strips off a single-quote that either begins or ends a token.

Make that fix. Test it and make sure that it is working, and commit it to your repository.

5. Turn in

Make a typescript showing your program FileProcessor2 running on one of the sample files given.

Turn in your source files and typescript with a command like

$ /cslab/class/csci235/bin/handin lab14 *.java typescript