CSCD 211 › lessons

Prerequisite: equals, built from "when are two objects the same?"

This is a bridge, not a refresher. You wrote an equals method in CSCD 210. This lesson shows you what it secretly was, the whole time, and why CSCD 211 cannot take its first real step without it. The climb is short and every rung is a click to collect. Even though you have seen equals before, the idea at the top is one most students meet here for the first time.

Quick check before you climb (retrieval first)

Answer these from memory before reading on. There are no stakes; the point is to wake up what 210 already left you with, because retrieving it now is what makes the new idea stick.

Check yourself. In 210 you compared two objects with == and you also wrote an .equals method. In one sentence each, what does == ask about two objects, and what did your .equals let you ask instead?

The point

By the end you can state the five-part equals contract and the three equivalence-relation rules at its core, you can see that those three rules are the axioms of an equivalence relation you already met in discrete math, and you can explain why Week 1's central promise, an order that agrees with equality, cannot even be stated until equals is solid. One climb, each rung a click.

The problem (sit with this before reading on)

The registrar imports the fall catalog, then imports a corrected copy of the same catalog to pick up a few edits. Two Course objects now exist for CSCD 211-001, built at different times from slightly different rows. The de-duplication step asks the obvious question, are these the same course, and it asks it like this:

if (a == b) {
    // treat as one course
}

It never matches. Every course in the catalog is silently doubled. Nothing in that line looks wrong, and the reason it fails is the first rung of the climb.

Check yourself. Both objects describe CSCD 211-001 in the same term. In one sentence, why does a == b report false anyway?

Rung 1: == asks for the same arrow, .equals asks for the same contents

Recall the box-and-arrow idea: a variable that holds an object holds an arrow to it, not the object itself. So a == b compares the two arrows. It is asking the narrow question, is this literally the one same object, and for two objects built separately the honest answer is no. To ask the question the registrar actually means, are these two objects equal in content, you call .equals:

if (a.equals(b)) {
    // treat as one course
}

That one change fixes the de-duplication, because Course.equals compares the fields that make a course the course it is, not the memory address. This is the same distinction under two names: == is identity, same object; .equals is value, same contents.

Collectible insight. Same arrow versus same contents: == asks identity, .equals asks value. For anything you built with new, you almost always mean .equals.

Check yourself. You have Course x = catalog.load("CSCD 211-001"); Course y = catalog.load("CSCD 211-001"); loaded twice from the same row. Predict x == y and x.equals(y), and say which one the registrar wants.

Rung 2: an equals method is a promise, and the promise has five parts

In 210 you wrote equals and it worked, so it is tempting to think any reasonable body will do. It will not. An equals method makes a promise to every collection and every caller that will ever use it. The Java contract for equals has five parts (the Object.equals specification in the Java API). Three of them are the equivalence-relation rules at the heart of this lesson:

Two more keep the promise honest. Consistent: repeated calls on unchanged objects give the same answer every time. Non-null: a.equals(null) is always false, never a crash. These are not style advice; a HashSet or a TreeSet quietly breaks if you violate the three equivalence rules, and a careless null check throws an exception instead of returning false.

Read them once and they sound obvious. The value is in naming them, because the moment your equals compares against the wrong type, or forgets a field, or treats null carelessly, it breaks one of the five, and the bug shows up far away inside a collection that trusted the promise.

Check yourself. Suppose someone writes a Course.equals so that a.equals(b) is true but b.equals(a) is false. Which of the three rules is broken, and name one place that would bite?

Rung 3: the click, those three rules are an equivalence relation

Here is the idea most students meet for the first time, even on a second reading. Reflexive, symmetric, and transitive are not three rules Java invented for equals. They are the exact definition, in discrete math, of an equivalence relation: a relation that sorts a set into groups where everything in a group counts as the same. Your Course.equals is an equivalence relation on the set of all Course objects, and the groups it creates are the sets of objects that describe one real course.

You have seen this structure before. Equality of fractions is an equivalence relation: one half and two fourths are different objects that count as the same value, and the rule that decides it is reflexive, symmetric, and transitive. Your equals defines an equivalence relation on Course, the same kind of structure that decides when two fractions count as one value.

And it pays off the moment you reach a hash-based collection. A HashSet<Course> puts objects that are equal into the same bucket, so it can find duplicates fast. Those buckets are the groups, the equivalence classes, made concrete in memory. The math word and the runtime data structure are the same thing seen twice.

But a hash set finds the bucket from hashCode, then confirms a match with equals. So equality has a partner rule that lives on a second method: equal objects must return equal hash codes. If you override equals and forget to override hashCode, two equal courses can land in different buckets, the set never compares them, and the de-duplication you just fixed silently breaks again (the Object.hashCode contract in the Java API states this directly). Equal objects, equal hash codes, is what makes the buckets line up with the equivalence classes.

Collectible insight. equals and hashCode are a pair: equal objects must return equal hash codes, or a hash set scatters equal objects into different buckets and stops finding duplicates. Override one, override both.

Going deeper (optional). The same three rules define an equivalence relation in Rosen, Discrete Mathematics, section 9.5, and the partition into equivalence classes is the matching theorem there. If you are taking or about to take discrete math, this is that exact section, and the cs-to-math cross-tree link collects it, so reviewing equals for 211 also feeds your math course.

Collectible insight. Equality is an equivalence relation: reflexive, symmetric, transitive. A hash set's buckets are its equivalence classes.

Check yourself. In one sentence, say what the buckets of a HashSet<Course> correspond to in the language of this rung.

Rung 4: why Week 1 cannot start without this

Week 1's central rigor is one sentence: a type's natural order should agree with its equality. In code, the guideline is that compareTo returns zero for the same pairs where equals returns true. The Comparable contract (Java API) strongly recommends this and most types follow it, though it is not strictly required; BigDecimal is the famous exception, where new BigDecimal("1.0") and new BigDecimal("1.00") compare equal yet are not equals. Read that sentence again and notice what it leans on. It is a statement about equals. You cannot understand what it means for an order to agree with equality until equality itself is a solid, three-rule promise in your mind. That is why this prerequisite comes first: the whole Week 1 contract is built on the floor you just re-laid.

So the climb ends pointed straight at the next idea. You have equality as an equivalence relation. Week 1 adds order as its partner, and then insists the two agree. The rung above this one is the first lecture of the term.

Check yourself (competency close). Finish this sentence in your own words: "I can explain that equals is an equivalence relation, which means , and Week 1 needs it because ."

What you collected

Walk into Tuesday knowing not just that you wrote equals once, but what it is and why the first real idea of the course stands on it.