Assignment 4 — Ordering
Teach Matrix its natural order so Arrays.sort will sort it, then write comparators for the orders it does not have. Find the place where compareTo and equals disagree, and fix it. Then do the whole thing again to Fraction, where the disagreement never happens.
Due Sep 22, 2026
Note: “AI” below means your favorite chatbot, e.g. Google Gemini, Microsoft Copilot, ChatGPT. Where a step does not say otherwise, AI tools are not allowed, as set out in the AI policy in the syllabus.
This one has its own repo. Accept it the same way you accepted A3, and clone it. What you get is two classes you have already met, both finished: the Matrix from A3, with every method written and every test passing, and the Fraction from A2. Neither one is yours to fix. This assignment is about ordering.
Your own Matrix or Fraction is welcome instead. If yours works and you would rather build on it, copy your file over the one in the new repo and commit that before you start — one commit, on its own, so the swap is visible in the history. Both ways are fine and neither earns or loses anything. Nothing below cares which one you kept.
Build and run the same way as before:
javac -d out src/*.java
java -ea -cp out MatrixTest
A floor, if you run out of time. Tasks 1 to 4 are the ones to get working. They are the whole of the idea — one order that the library knows how to use, and one more that you supply yourself — and everything after them is a variation on it. Push what you have even if it is only the floor. Partial work you pushed beats finished work you did not.
Parts 3 and 4 are the ones to start early if you can. Not because they are worth more, but because each of them asks you to write down a prediction before you run the code, and that goes badly in a hurry. A guess you wrote and then watched fail is the part that teaches; a guess you skipped to save four minutes is four minutes.
Part 1 — the order a matrix already has
Make
MatriximplementComparable<Matrix>. Addimplements Comparable<Matrix>to the class declaration and write the one method it requires:@Override public int compareTo(Matrix other)Order matrices by
magnitude(), smallest first.magnitude()is already there.The method returns any negative number when
thiscomes first, any positive number when it comes second, and zero when neither does. It does not have to be -1, 0 and 1.Do not subtract two magnitudes and cast the result to
int. Magnitudes aredoubles, and two matrices 0.4 apart both cast to 0 — so the sort quietly decides they are equal.Double.comparedoes this correctly in one line; look at what it returns before you use it.Sort an array. Write
src/SortMatrices.javawith amainthat builds an array of at least four matrices with different magnitudes, prints the array, callsArrays.sorton it, and prints it again.You need
import java.util.Arrays;for this.Nothing in
Arraysknows anything about your class. It works because task 1 kept a promise.
Part 2 — the orders it does not have
Write
src/MagnitudeDescending.java, a class implementingComparator<Matrix>, that orders matrices largest first.Get the reverse order by comparing the two matrices the other way round, not by negating the result of
compareTo. Negating looks equivalent and is not: the most negativeinthas no positive counterpart, so negating it gives you back a negative number and the order silently breaks.Sort the same array with it, in the same
main, and print the result.Arrays.sorttakes a comparator as a second argument.Matrixdid not change between task 2 and task 4. That is the point of this part: the sorted order is not a property of the class.Write
src/BySize.java, aComparator<Matrix>that orders matrices by row count, and breaks ties by column count. Sort with it and print the result.Two matrices with the same shape are equal as far as this comparator is concerned, however different their numbers are. That is allowed, and Part 3 is about what it costs.
Part 3 — where the two contracts disagree
Build two matrices that are different but have the same magnitude, and predict what this prints before you run it:
Matrix a = /* your first matrix */; Matrix b = /* your second matrix */; Set<Matrix> hashed = new HashSet<>(List.of(a, b)); Set<Matrix> sorted = new TreeSet<>(List.of(a, b)); System.out.println(hashed.size() + " " + sorted.size());Write your prediction in a comment above the code, then run it. Leave the comment in even if the prediction was wrong — especially then.
[[1, 0], [0, 0]]and[[0, 1], [0, 0]]are one pair that works, and there are many others.Make
compareToagree withequals. ChangecompareToso that it returns zero only for matrices that are alsoequalsto each other, and re-run task 6.Compare the magnitudes first, as now. When those are equal, keep going: compare the shapes, and then the numbers, until you find something that differs. Two matrices that are
equalswill run out of things to compare, and that is when you return zero.The javadoc for
Comparablecalls this being consistent with equals, and says it is “strongly recommended” rather than required. Task 6 shows you what the recommendation is protecting.
Part 4 — the same four ideas, on a different class
Everything above happened to Matrix. None of it was about matrices. Part 4 is the proof: the same four moves — a natural order, a comparator, equals, and the place where the two contracts meet — on Fraction, which is already in your repo and is finished.
Make
FractionimplementComparable<Fraction>, ordering fractions by value, smallest first.-1/4comes before1/3, which comes before1/2.Do not subtract one fraction from the other and cast to
int. It is the task 1 mistake wearing a different coat, and it is worse here: every fraction strictly between -1 and 1 subtracts to something that casts to 0, soArrays.sortdecides most of your array is already in order and leaves it alone. Run it once if you want to see what that looks like.Compare
a/bagainstc/dby comparinga*dagainstc*binstead. Two things to get right. First, multiplying twoints does not give you anintwhen the numbers get large —Long.compareand a cast fix that. Second, cross-multiplying like this is only valid when the denominators are positive, because multiplying an inequality by a negative number flips it. Open the constructor and find out whether they are. Do not assume either answer.Write
src/SortFractions.javawith amainthat builds an array of at least four fractions, prints it, callsArrays.sort, and prints it again. Include at least one negative fraction.Give
FractionagetNumerator()and agetDenominator(), both returningint.numanddenareprivate, and task 11 needs to read them from a different class. A comparator is not a friend of the class it sorts — it sees the public surface and nothing else. Two accessors are the whole fix, and they hand out copies of twoints, which is not a leak.Write
src/ByDenominator.java, aComparator<Fraction>that orders fractions by denominator alone, smallest first.1/3and2/3tie under it, and so do1/2and-1/2. That is the same situationBySizewas in back in task 5.Give
Fractionanequalsand ahashCode. Two fractions are equal when they have the same numerator and the same denominator.Same rules as
Matrix:equalstakes anObject, and anything that isequalsmust have the samehashCode.Run the task 6 experiment again, on fractions. In the same
main, write down what you expect before you run it:Fraction p = new Fraction(2, 4); Fraction q = new Fraction(1, 2); Set<Fraction> hashed = new HashSet<>(List.of(p, q)); Set<Fraction> sorted = new TreeSet<>(List.of(p, q)); System.out.println(hashed.size() + " " + sorted.size());Then, in a comment underneath, answer this in two or three sentences:
Matrixneeded task 7 to makecompareToandequalsagree.Fractiondid not. Why not?The answer is in what each order is built on.
magnitude()is one number computed from a matrix; a fraction’s value is the fraction. Say what follows from that.
Handing in
Commit and push. The last commit before the deadline is what gets marked.
Every push is graded, one check at a time, and the result lands on your feedback pull request — so push early and read what failed, rather than saving it all for the last night.
A student picked at random presents this one in class the following Wednesday.