Lab 19: Sortable Roster
Comparable, compareTo, sorting objects, and file round-trip
After this lab, you will be able to:
- Implement the
Comparableinterface with acompareTomethod - Sort objects using
Arrays.sortwith natural ordering - Add a multi-field sort with tiebreakers
- Read objects from a file, sort them, and write the sorted result back
What You’re Building
You will extend your Student class (or a fresh copy) to implement Comparable<Student>, enabling Arrays.sort to order students by GPA. When two students have the same GPA, the sort breaks ties alphabetically by name. The program reads a roster from a file, creates an array of Student objects, sorts them, and writes the sorted roster to an output file. This is a full-week lab because the interface pattern is new and the file round-trip adds integration complexity.
Timeline: This lab is assigned Monday and due Friday. Start with
compareToand test it in isolation before adding file I/O.
Concepts and Misconceptions
| Concept | Common Mistake | What the Test Catches |
|---|---|---|
implements Comparable<Student> |
Forgetting the generic type, writing Comparable without <Student> |
Compiler warning; compareTo receives Object instead of Student |
compareTo |
Subtracting doubles directly ((int)(this.gpa - other.gpa)) — truncation loses precision |
Students with GPA 3.4 and 3.5 compare as equal |
| Tiebreaker | Returning 0 immediately when GPAs are equal, ignoring the name tiebreaker | Students with the same GPA appear in unpredictable order |
Arrays.sort |
Calling Arrays.sort on an array with null elements |
NullPointerException during sort |
| File round-trip | Parsing the GPA as int instead of double, or splitting on the wrong delimiter |
Parse errors or garbled student data |
Checkpoints
Checkpoint 1: Implement Comparable and compareTo by GPA
What to do: Add implements Comparable<Student> to your class declaration. Write compareTo(Student other) that orders students by GPA in descending order (highest GPA first). Use Double.compare to avoid precision issues with subtraction.
What the test checks: compareTo returns a negative value when this student’s GPA is higher, a positive value when lower, and 0 when equal.
Debugging tip: If the sort order is backwards (ascending instead of descending), you have the arguments to Double.compare reversed. For descending GPA: Double.compare(other.gpa, this.gpa). If students with the same GPA produce a nonzero result, check that you are comparing only GPA in this step, not name.
Checkpoint 2: Name Tiebreaker and Arrays.sort
What to do: When two students have the same GPA, break the tie by comparing names alphabetically (ascending). Use this.name.compareTo(other.name) for the tiebreaker. In your main method, create an array of students and call Arrays.sort.
What the test checks: An array of students with mixed and duplicate GPAs is sorted by descending GPA, then ascending name.
Debugging tip: If the tiebreaker is not working, make sure you only fall through to the name comparison when the GPA comparison returns 0. A common pattern: int result = Double.compare(other.gpa, this.gpa); if (result != 0) return result; return this.name.compareTo(other.name);. If Arrays.sort throws a NullPointerException, check that every slot in your array has been assigned a Student object.
Checkpoint 3: Load from File, Sort, and Write Output
What to do: Read a roster file where each line contains a name, ID, and GPA separated by commas. Parse each line into a Student object and store them in an array. Call Arrays.sort on the array. Write the sorted roster to an output file using PrintStream, one student per line (use toString).
What the test checks: The output file contains all students in the correct sorted order, with each line matching the expected toString format.
Debugging tip: If parsing fails, print each line before splitting it. Check that you handle leading/trailing whitespace with trim(). When parsing GPA, use Double.parseDouble, not Integer.parseInt. If the output file is empty, verify that you close the PrintStream after writing.
How to Debug
-
Test
compareToin isolation. Create three students inmain— one with a higher GPA, one lower, one equal — and print the results ofcompareTofor each pair. Verify the signs are correct before usingArrays.sort. -
Print the array before and after sorting. Use
Arrays.toStringor a loop to print every element. This makes it obvious if the sort is working or if null elements are present. -
Separate concerns. Get the sort working with hardcoded data first. Only then add file reading. This way, if something breaks, you know which part is the cause.
Scoring
| Component | Points | Criteria |
|---|---|---|
| Checkpoints | 3 | 1 pt each. Binary: the checkpoint test passes or it does not. |
| Autograder | 5 | Correctness across all test cases. Partial credit by proportion of tests passed. |
| Timeliness | 2 | Full credit if submitted by the due date. 0 if late. |
| Total | 10 |