← Skill tree CS Skill Tree 0 CSCD211

The cscd211Comparators Package Convention

Textbook: BJP (Reges and Stepp)

Before You Start

Check each box you can do from memory. A box you cannot check yet is not a problem; it points you to a quick refresher, not a grade.

Not sure? Take the 60-second self-check.

1. Package declaration. Where in a Java source file does the package declaration appear?

Check

Line 1 of the file, before any import statements and before the class declaration. It takes the form package packageName;.

2. Import statement. A class in package cscd211Comparators needs to use Player from cscd211Classes. What import statement is required?

Check

import cscd211Classes.Player;

3. Package vs. directory. If a file is physically placed in the cscd211Comparators/ directory but has no package declaration, what package does Java consider it to be in?

Check

The default (unnamed) package. A class in the default package cannot be imported by name from another package. The physical directory and the declared package are separate; both must agree.


Try This First

Look at this directory listing from F19 Lab 1:

cscd211Classes/
    Player.java
    Team.java
cscd211Enums/
    NFLTeam.java
    Position.java
cscd211Comparators/
    TeamComparator.java
    PositionComparator.java
    GamesPlayedComparator.java
cscd211Methods/
    CSCD211Lab1Methods.java
cscd211Lab1/
    CSCD211Lab1.java

Before reading further: a new requirement asks for a fourth comparator that orders players by jersey number. Write down (a) which directory the new file goes in and (b) what the first two non-blank lines of the file are.

Check

(a) The file goes in cscd211Comparators/.

(b) Line 1: package cscd211Comparators; Line 2 (blank), then the import: import java.util.Comparator;


What You Need To Walk In With

Player is data. TeamComparator is a strategy for ordering that data. Separating them into different packages makes the dependency direction visible in the directory tree: comparators depend on data classes, but data classes know nothing about comparators. Deleting all comparator files leaves Player.java untouched. Deleting Player.java would break every comparator in the package.

If the package and import mechanics feel uncertain right now, focus on the two required lines at the top of every comparator file: write them before the class declaration, every time, and the compiler will tell you if the directory does not match. You can: name all five standard CSCD 211 packages and what each one holds, write the correct package declaration and import statements for a new comparator from scratch, predict the compile error a missing package declaration causes, and explain the one-way dependency that keeps data classes free of comparator knowledge.


How It Works

The five-package layout

CSCD 211 labs follow this structure (from F19.Lab1-Review):

Package Contents
cscd211Classes Data types: Player, Team, Book
cscd211Enums Enum types: NFLTeam, Position, Genre
cscd211Comparators Named Comparator classes: TeamComparator, PositionComparator, ...
cscd211Methods The lab’s main class and helper methods
cscd211Utils Provided utilities (ArrayUtils, FileUtils, etc.) shipped as a JAR

The complete structure of a comparator file

Every file in cscd211Comparators follows this header:

package cscd211Comparators;               // line 1: package declaration

import java.util.Comparator;              // required: brings in the interface
import cscd211Classes.Player;             // required: brings in the type being compared

public class TeamComparator implements Comparator<Player>
{
    @Override
    public int compare(final Player a, final Player b)
    {
        if (a == null || b == null)
            throw new IllegalArgumentException("Bad Player in TeamComparator.compare");
        return a.getTeam().compareTo(b.getTeam());
    }
}

Four things must be in place:

Item What goes wrong if it is missing
package cscd211Comparators; The class lands in the default package; any import cscd211Comparators.TeamComparator; in another file fails to resolve
import java.util.Comparator; The interface name Comparator does not resolve; the compiler reports a symbol-not-found error
import cscd211Classes.Player; The type Player does not resolve; the compiler reports a symbol-not-found error
public class ... The class is package-private; it cannot be instantiated from cscd211Lab1 (a different package)

Quick check

Check your understanding

A file named RatingComparator.java compares Movie objects from cscd211Classes. Which header exactly matches the required package declaration and two import statements?

Tier 2 · BJP (Reges and Stepp), Ch 10

Why comparators belong in their own package

The cscd211Classes package contains the domain model. It is the answer to the question “what data does this lab work with?” Adding comparators to that package mixes two concerns: “what is a Player?” and “in what orders can we sort Players?” These are separate questions that change for separate reasons.

The cscd211Comparators package contains the answer to the second question alone. Keeping them separate makes both questions easier to answer from the directory listing.

Singular vs. plural: a real drift

Labs from F17 and SP19 sometimes use cscd211Comparator (singular) instead of cscd211Comparators (plural). The correct spelling for current labs is cscd211Comparators (plural). If an IDE auto-completes the import and offers both spellings, pick the one that matches the package declaration at the top of the comparator file.


Worked Example: Predict Then Check

A student creates JerseyNumberComparator.java and places it in the cscd211Comparators/ directory but forgets to add the package declaration. The main class in cscd211Lab1/CSCD211Lab1.java contains:

import cscd211Comparators.JerseyNumberComparator;

Predict the compile error and state the fix.

Step-by-step reasoning

The file has no package declaration, so the compiler places it in the default package. The import statement import cscd211Comparators.JerseyNumberComparator looks for a class named JerseyNumberComparator in the package cscd211Comparators. That class does not exist in that package because it is in the default package. The import fails to resolve.

Show answer

Compile error (in CSCD211Lab1.java):

error: cannot find symbol
import cscd211Comparators.JerseyNumberComparator;
       ^

Fix: Add package cscd211Comparators; as the first line of JerseyNumberComparator.java.

Source: JLS §7.4 (Package Declarations).


Common Misconceptions

Misconception 1: comparators belong in the same package as the class they compare

Wrong mental model: “TeamComparator works with Player, so it should be in cscd211Classes/ alongside Player.”

Why it breaks: cscd211Classes is the domain model. Adding comparators to it mixes two concerns that change for separate reasons. The directory listing no longer separates “what data exists” from “how to sort that data.” More practically, adding a fifth comparator later requires editing the cscd211Classes package, which also contains entirely unrelated classes.

How to correct: Comparators go in cscd211Comparators. The dependency runs one way: comparators import from cscd211Classes; cscd211Classes imports nothing from cscd211Comparators.


Misconception 2: placing the file in the correct directory is sufficient

Wrong mental model: “I put JerseyNumberComparator.java inside cscd211Comparators/. The compiler knows it is in that package.”

Why it breaks: The compiler does not infer the package from the directory path. Without package cscd211Comparators; on line 1, the class is in the default package. The import statement in the main class fails to resolve it.

How to correct: Line 1 of every comparator file must be package cscd211Comparators;. The directory and the package declaration must agree; neither substitutes for the other.

Source: JLS §7.4.

Quick check

Check your understanding

A student places BookComparator.java inside cscd211Comparators/ and writes the class body correctly, but the first line of the file is ‘import java.util.Comparator;’ with no package declaration above it. What is the outcome when the main class tries to compile ‘import cscd211Comparators.BookComparator;’?

Tier 2 · JLS §7.4 (Package Declarations)


Formal Definition and Interface Contract

From JLS §7.4 (Package Declarations):

A package declaration in a compilation unit specifies the package to which the compilation unit belongs. [...] If a compilation unit has no package declaration, it is considered to be part of an unnamed package.

From JLS §7.6 (Top Level Type Declarations):

A class or interface may be accessed from code in packages other than the package in which it is declared only if the class or interface is declared public.

These two rules explain why the package declaration must be present and why the comparator class must be public when the main class is in a different package.


Mental Model

Think of the project layout as a building with labeled floors. The ground floor (cscd211Classes) holds the raw materials. A separate floor (cscd211Comparators) holds the tools for sorting those materials. Tools depend on materials; materials do not carry tools around. If you move a tool to the materials floor, neither changes functionally, but the directory listing no longer tells you which floor is which. The package declaration is the floor number posted on the door.


Connections

Within CSCD 210/211: Every CSCD 210 lab uses multiple packages. The Steiner layout in CSCD 211 adds cscd211Comparators as a new destination for a new kind of class. The mechanics (package declaration, import) are unchanged from CSCD 210.

Looking back: Implementing Comparator&lt;T&gt; as a Named Class established how to write the body of a comparator class. This lesson establishes where that class lives and how its file header is constructed.

Looking ahead: Instantiating a Comparator and Passing It to Arrays.sort covers how the main class imports the comparator, creates an instance, and passes it to Arrays.sort.


Go Deeper (optional)

None of what follows is needed to write correct comparator code. It is here for readers who want to see where the ideas connect to larger territory.

The Steiner layout is a teaching-scale version of what architects call the layered pattern: data-transfer objects in one layer, business logic (in this case, sorting strategies) in another, utilities in a third. In large production codebases the same principle appears, sometimes organized by layer (all service classes together, all data classes together) and sometimes by feature (all files for one product feature together). Either way, the underlying contract is identical to what you practiced here: the direction of imports encodes which layer depends on which, and data types do not carry sorting strategies around inside them.

A Comparator is also, from a design-pattern perspective, the Strategy pattern in its simplest form: you separate the algorithm (how to compare two things) from the objects being compared (the data). Each named comparator class is one interchangeable strategy. This is also the earliest example in the course of a function being treated as a value, something you will formalize when lambdas appear later.

For readers interested in the language specification: Bloch, Effective Java, Item 15 argues for minimizing accessibility, which is the same principle that gives package boundaries their meaning. The Java Platform Module System (JPMS, introduced in Java 9) takes this one step further by making inter-package dependencies explicit at the language level: a module must declare which of its packages it exports, and code in another module cannot see packages that are not exported. The cscd211Comparators package importing from cscd211Classes while cscd211Classes exports nothing back is precisely the structure JPMS was designed to enforce at scale.

In professional code you will encounter this pattern in standard library internals, in frameworks that use comparator injection (passing a sort strategy into a data structure), and in any system where the ordering of records must change without touching the records themselves.


Practice

Level 1

Write the complete file header (package declaration, import statements, class declaration) for a new BookByPagesComparator class that orders Book objects (in cscd211Classes) by page count. Do not write the method body.

Thought process

Follow the template: package declaration first, then imports (one for Comparator, one for Book), then the class declaration with implements Comparator<Book>.

Show answer
package cscd211Comparators;

import java.util.Comparator;
import cscd211Classes.Book;

public class BookByPagesComparator implements Comparator<Book>
{
    @Override
    public int compare(final Book a, final Book b)
    {
        // body goes here
    }
}

Level 2

Given this directory listing:

cscd211Classes/    → Product.java
cscd211Enums/      → Category.java
cscd211Comparators/→ ProductByPriceComparator.java
cscd211Methods/    → Lab3Methods.java

A student’s ProductByPriceComparator.java begins with:

import java.util.Comparator;
import cscd211Classes.Product;

public class ProductByPriceComparator implements Comparator<Product>

Lab3Methods.java contains import cscd211Comparators.ProductByPriceComparator;. The build fails. Identify the problem and state the fix in one line.

Show answer

The comparator file is missing its package declaration. It is in the default package. The fix: add package cscd211Comparators; as the first line of ProductByPriceComparator.java.


Level 3

Explain in 3-4 sentences why the Steiner lab layout places TeamComparator in cscd211Comparators rather than in cscd211Classes. Include in your answer: (a) the direction of the dependency, (b) what happens to Player.java if all comparator files are deleted, and (c) which Bloch item supports this design.

Show answer

The dependency runs one way: TeamComparator imports cscd211Classes.Player, but Player imports nothing from cscd211Comparators. Placing both in the same package would hide that asymmetry. If all comparator files are deleted, Player.java still compiles and runs without modification; Player has no knowledge of and no dependency on the comparators. Keeping comparators in their own package encodes separation of concerns at the file-system level, making it immediately clear which code is the domain model and which code is a sortation strategy. Bloch, Effective Java, Item 15 (minimize accessibility) supports this design by encouraging narrow, explicit package boundaries.


Check Yourself

Close the notes and answer each one from memory, then reveal it. Pulling an idea back from memory is one of the strongest ways to make it stick.

Check your understanding

Which of the five standard CSCD 211 packages is the correct home for a class named TeamComparator?

Tier 1 · BJP (Reges and Stepp), Ch 10

A student places JerseyNumberComparator.java inside the cscd211Comparators/ directory but omits the package declaration. What does the Java compiler do with this class?

Tier 2 · JLS §7.4 (Package Declarations)

In the five-package Steiner layout, which direction does the dependency run between cscd211Comparators and cscd211Classes?

Tier 2 · BJP (Reges and Stepp), Ch 10

Trace the compile outcome. Lab3Methods.java (in cscd211Methods) contains: import cscd211Comparators.ProductByPriceComparator; ProductByPriceComparator.java is in the cscd211Comparators/ directory. Its first non-blank line is: import java.util.Comparator; (no package declaration above it). What does the compiler report when building Lab3Methods.java?

Tier 3 · JLS §7.4 (Package Declarations)

Which two import statements are required in the header of every file in cscd211Comparators that compares Player objects?

Tier 1 · BJP (Reges and Stepp), Ch 10