CISC 3115

Exercise 2: StringPile

Objectives:

The Goal

At the end of unit 2, we spent a little time in class on a program to do some String operations. In this exercise, you'll end up in the same place, but instead of just writing a main program, you're going to design and implement a class that does the real work.

The StringPile class

To remind you, here's the activity from unit 2:

Imagine a program that reads an arbitrary number of Strings in from the input (where each line of input is treated as a String), then outputs: the shortest String (if multiple Strings have the shortest length, output the one that occurs first in the input), the longest String (again, if multiple Strings have the longest length, output the first-occurring one), and print the Strings in alphabetical order.

So the StringPile class is going to do most of that work. In particular, here's the class "skeleton":

      public class StringPile {
        public void load(Scanner sc)
        public String getShortest()
        public String getLongest()
        public void printInOrder(PrintStream ps)
      }

A couple notes:

Remember that you are not to implement the sort yourself, but to use the Java API. Also note that you can detect the end of the input with a Scanner object by using the hasNextLine() method.

Your Task

So, you have three things to do.
  1. Implement the StringPile class. Notice that there is nothing here about implementation details. Do you need instance variables? Do you need to write any "helper" methods? What exactly should the load() method do? Another thing to think about: must every "get" method correspond to an instance variable?
  2. Use your StringPile class to implement the exercise.
  3. Create some test data and test your application.

Note you can do these in any order, or work on them simultaneously, as you wish: once you have the method signatures established, the implementation, application, and testing of them should be totally separate.

For a little more fun

ArrayLists are supposed to work on arbitrarily large datasets, right? So try your code on this file of nearly 500,000 words. When we get to that amount of data, the efficiency of your code really starts to make a difference. How long does each of your methods take to do its work?

Fortunately, the Java API includes some methods to help us find out. this page has a more detailed explanation, but here's the code we need to time the execution of a chunk of code:

      long startTime = System.nanoTime();

      // ... this is the code we want to time ...

      long endTime = System.nanoTime();
      System.out.println("That took " + (endTime - startTime)/1000000.0 + " milliseconds);
(Note that I divided by a million in floating point to get fractional milliseconds.)

Use this technique to time the calls to the four methods in your StringPile implementation. These should be, y'know, pretty fast, though the exact timings will depend on your hardware and other factors.

Final Thoughts

As you're working on this (or when you're done), think about this: what about making a "generic" Pile class? That is, could we, in theory, write a version of this that would work for any type of object? (We haven't talked about the actual programming techniques for doing this, but we've seen how the ArrayList class is designed to serve as an "array" of any type of object.) If your answer is "yes," what kinds of changes would you have to make to your code? If your answer is "no," what's your problem? Do you mean this can only work for Strings, or only some kinds of objects, or what?