Comparable vs Comparator

Java can sort numbers and Strings out of the box, but how should it sort students, orders or trains? You have to tell it. Comparable puts one natural order inside the class (compareTo). Comparator describes extra orders outside it (compare): by marks, by name, by date, highest first, ties broken by roll number. You'll learn both, how sorting algorithms call them, and the small bugs that make sorts go wrong.

Module 11 · Collections⏱ 24 minIntermediate8 practice problems
1 The story

One class, three rank lists

The exam cell needs three printouts of the same students: by roll number for the attendance register, by marks (highest first) for the merit list, and by name for the certificate desk. Kabir calls Collections.sort(students) and gets a compile error.

By roll (natural)Comparable 07 Riya 9212 Kabir 7821 Om 92 Merit listComparator: marks ↓, roll 07 Riya 9221 Om 9212 Kabir 78 CertificatesComparator: name 12 Kabir 7821 Om 9207 Riya 92 myphatshala.in
Riya

Sir, Java sorts numbers and names fine. Why can't it sort students?

Arjun Sir

Because it doesn't know what “smaller” means for a student. Roll number? Marks? Name? You choose. If one order is the obvious, everyday one, like roll number, put it inside the class by implementing Comparable.

Riya

And the merit list and certificates?

Arjun Sir

Those are extra orders, so write them as Comparators outside the class and pass them to sort. One class, as many orders as the exam cell wants, and modern Java builds them in one line.

2 Definition

What are Comparable and Comparator?

Formal definition (write this in exams)

Comparable<T> (java.lang) is implemented by a class to define its natural ordering through the single method int compareTo(T other). Comparator<T> (java.util) is a separate object that defines an ordering through int compare(T a, T b), allowing multiple orderings and ordering of classes you can't modify. Both return a negative integer if the first argument comes before the second, zero if they are equal in the ordering, and a positive integer if it comes after. Sorting methods (Collections.sort, List.sort, Arrays.sort) and sorted collections (TreeSet, TreeMap, PriorityQueue) use the natural ordering unless a Comparator is supplied.

In simple words

Comparable: “this is how my objects are normally ordered”, written in the class. Comparator: “sort them this way for now”, written anywhere.

Words you'll meet in this lesson

Natural orderingThe one default order of a type: numbers ascending, Strings alphabetical.
Sort keyThe field you sort by: marks, name, date.
Tie-breakerA second key used when the first is equal.
Stable sortEqual elements keep their original relative order. Java's object sorts are stable.
LexicographicDictionary order by character codes: “Zoya” < “riya” because capitals come first.
Method referenceStudent::marks means “call marks() on each student” (Lesson 14.1).

Comparable vs Comparator

ComparableComparator
Packagejava.langjava.util
MethodcompareTo(T other)compare(T a, T b)
WhereInside the class being sortedA separate object (class, lambda, method reference)
How many ordersOne natural orderAs many as you like
Use withCollections.sort(list), new TreeSet<>()list.sort(cmp), new TreeSet<>(cmp)
Classes you can't editNot possibleWorks fine

Exam tip: only the sign of the result matters (negative / zero / positive), not the size. And compareTo should be consistent with equals: a.compareTo(b) == 0 exactly when a.equals(b); otherwise TreeSet/TreeMap behave strangely (Lesson 11.5).

3 Types and ways to use it

From one natural order to many custom ones

Comparable

Implement compareTo in the class. Sorting needs no arguments.

natural order

Comparator class / lambda

(a, b) -> Integer.compare(a.marks, b.marks)

custom order

Comparator builders

comparing, thenComparing, reversed, nullsFirst.

readable

Comparable: the natural order

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Student implements Comparable<Student> {
    final int roll;
    final String name;
    final int marks;

    Student(int roll, String name, int marks) {
        this.roll = roll;
        this.name = name;
        this.marks = marks;
    }

    @Override
    public int compareTo(Student other) {
        return Integer.compare(this.roll, other.roll);   // by roll number
    }

    @Override
    public String toString() { return roll + " " + name + " " + marks; }
}

public class Main {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>(List.of(
            new Student(21, "Om", 92), new Student(7, "Riya", 92), new Student(12, "Kabir", 78)));
        Collections.sort(list);                 // uses compareTo
        System.out.println(list);
    }
}
[7 Riya 92, 12 Kabir 78, 21 Om 92]

Comparators: any order you need

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

class Student {
    final int roll; final String name; final int marks;
    Student(int roll, String name, int marks) { this.roll = roll; this.name = name; this.marks = marks; }
    int roll() { return roll; }
    String name() { return name; }
    int marks() { return marks; }
    @Override public String toString() { return roll + " " + name + " " + marks; }
}

public class Main {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>(List.of(
            new Student(21, "Om", 92), new Student(7, "Riya", 92), new Student(12, "Kabir", 78)));

        // 1. A Comparator written as a lambda (Lesson 14.1)
        list.sort((a, b) -> a.name.compareTo(b.name));
        System.out.println("By name:  " + list);

        // 2. Built with Comparator.comparing: marks high→low, ties by roll
        Comparator<Student> merit = Comparator.comparingInt(Student::marks).reversed()
                                              .thenComparingInt(Student::roll);
        list.sort(merit);
        System.out.println("Merit:    " + list);
    }
}
By name: [12 Kabir 78, 21 Om 92, 7 Riya 92] Merit: [7 Riya 92, 21 Om 92, 12 Kabir 78]

Strings: case matters

import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(List.of("riya", "Zoya", "Kabir"));
        Collections.sort(names);                              // natural: by char codes
        System.out.println(names);
        names.sort(String.CASE_INSENSITIVE_ORDER);           // a ready-made Comparator
        System.out.println(names);
        names.sort(Comparator.reverseOrder());
        System.out.println(names);
    }
}
[Kabir, Zoya, riya] [Kabir, riya, Zoya] [riya, Zoya, Kabir]

The subtraction trap

public class Main {
    public static void main(String[] args) {
        int a = -2_000_000_000, b = 2_000_000_000;
        System.out.println(a - b);                  // overflows: looks positive!
        System.out.println(Integer.compare(a, b));  // correct: negative
    }
}
294967296 -1

Don't write return this.x - other.x; in compareTo. For large or negative values the subtraction overflows and the sign flips, so the sort silently goes wrong. Use Integer.compare, Long.compare, Double.compare or Comparator.comparingInt.

Rule of thumb: give a class a natural order only if there's one obvious, stable order (IDs, dates, version numbers). Everything else is a Comparator, ideally a named constant like Student.BY_MERIT built with comparing(...).thenComparing(...).

4 Step by step

What sort does with your comparator

  1. You hand over the rule

    list.sort(merit);
    List.sort copies the elements into an array and calls Arrays.sort(array, merit).
  2. The algorithm picks pairs

    Java sorts objects with TimSort, a merge sort tuned for real data (it finds already-sorted runs). For tiny arrays it uses binary insertion sort. It decides which two elements to compare next.
  3. Your method answers: before, same or after

    For each pair it calls merit.compare(a, b) (or a.compareTo(b)). Your code never moves elements; it only answers with a sign. The algorithm moves them.
  4. About n log n questions

    Sorting n elements needs roughly n·log₂n comparisons: about 10,000 for 1,000 students. That's why a comparator should be cheap and must be consistent (if a < b and b < c then a < c), or TimSort may throw Comparison method violates its general contract!.
  5. Stable result, written back

    The sorted array is copied back into the list. Because the sort is stable, students with equal keys stay in their previous relative order, which lets you sort by a secondary key first and the primary key second if you want.
5 See it happen

sort asks, your comparator answers: both views

Left: the list being sorted for the merit list. Right: each call to compare, its result, and what the sort does with it.

How sort uses your comparator 6 steps
What you see merit = comparingInt(marks).reversed() .thenComparingInt(roll); list.sort(merit); Om21 · 92 Riya07 · 92 Kabir12 · 78 roll · marks [Om, Riya, Kabir] (unsorted) [Riya, Om, Kabir] [Riya, Om, Kabir] ✓ merit order Three students to rank. sort is thinking… …still thinking… Two cards swap. Kabir stays last. Done. myphatshala.in
Behind the screen TimSort's questions to your comparator compare(Riya, Om) marks 92 = 92 → roll 7 vs 21 −1: Riya before Om compare(Kabir, Riya) marks 78 vs 92 (reversed) +1: Kabir after Riya compare(Kabir, Om) marks 78 vs 92 (reversed) +1: Kabir after Om run [Om, Riya] was descending → reverse it: [Riya, Om] your code only answered −1 / 0 / +1; TimSort moved the elements sort copies the list into an array. First question: Riya vs Om. Does the first run continue? Kabir vs Riya. TimSort reverses the descending run. Insert Kabir: compare with Om. 3 comparisons for 3 elements. myphatshala.in
6 Real-world use

Ordering in real systems

Every sorted screen, ranked list and priority queue in an app has a comparator behind it.

Watch it with an example: “Sort by” on a shopping app

The same four phones, re-sorted each time the shopper taps a different option. Each option is just a different Comparator.

One list, three comparators 4 steps
Animated example Phone A ₹14,999 ★4.2 Phone B ₹9,999 ★4.5 Phone C ₹14,999 ★4.6 Phone D ₹21,999 ★4.4 Sort by: as loaded Sort by: Price: low to high Sort by: Rating: high to low Sort by: Price: high to low, then rating comparingInt(Phone::price) comparingDouble(Phone::rating) comparingInt(Phone::price) .reversed() .reversed().thenComparing(…) Results arrive unsorted. Cheapest first; A and C tie at ₹14,999. Best rated first. Costliest first; the tie is broken by rating. myphatshala.in
Price ↑ | Rating ↓

1. “Sort by” menus

Shopping and travel apps offer “price low to high”, “rating”, “newest”. Each option is a Comparator (often with a tie-breaker like product ID so the order is stable across pages).

user picks “Price ↑”→comparing(Product::price)→sorted results
1. Riya 922. Om 92

2. Rankings and leaderboards

Exam results, sales leaderboards and cricket tables sort by a main score with tie-breakers (net run rate, then wins), exactly a thenComparing chain.

points ↓→thenComparing(nrr ↓)→league table

3. Priority processing

Support tickets by severity then age, hospital triage by condition, delivery jobs by deadline: a PriorityQueue with a Comparator always hands out the most urgent item next.

new ticket→PriorityQueue(bySeverity)→most urgent first
v1.10 > v1.9natural order

4. Natural orders in value types

Types like LocalDate, BigDecimal and app version numbers implement Comparable, so they sort correctly in TreeMaps and reports without extra code.

TreeMap<LocalDate, …>→compareTo→chronological report

Examples are simplified. Large lists are usually sorted by the database (ORDER BY) before reaching Java.

7 Run the code

Exam cell: three printouts from one list

import java.util.*;

class Student implements Comparable<Student> {
    final int roll;
    final String name;
    final int marks;

    Student(int roll, String name, int marks) {
        this.roll = roll;
        this.name = name;
        this.marks = marks;
    }

    int roll() { return roll; }
    String name() { return name; }
    int marks() { return marks; }

    @Override
    public int compareTo(Student o) { return Integer.compare(roll, o.roll); }

    @Override
    public String toString() { return String.format("%02d %-6s %d", roll, name, marks); }

    static final Comparator<Student> BY_MERIT =
        Comparator.comparingInt(Student::marks).reversed().thenComparing(Comparator.naturalOrder());
    static final Comparator<Student> BY_NAME =
        Comparator.comparing(Student::name, String.CASE_INSENSITIVE_ORDER);
}

public class Main {
    static void print(String title, List<Student> list) {
        System.out.println(title);
        for (Student s : list) System.out.println("  " + s);
    }

    public static void main(String[] args) {
        List<Student> students = new ArrayList<>(List.of(
            new Student(21, "Om", 92), new Student(7, "Riya", 92),
            new Student(12, "Kabir", 78), new Student(3, "zoya", 85)));

        Collections.sort(students);
        print("Register:", students);
        students.sort(Student.BY_MERIT);
        print("Merit list:", students);
        students.sort(Student.BY_NAME);
        print("Certificates:", students);
    }
}
Register: 03 zoya 85 07 Riya 92 12 Kabir 78 21 Om 92 Merit list: 07 Riya 92 21 Om 92 03 zoya 85 12 Kabir 78 Certificates: 12 Kabir 78 21 Om 92 07 Riya 92 03 zoya 85
  • implements Comparable<Student>The natural order: roll number. Collections.sort(students) uses it.
  • Integer.compare(roll, o.roll)Safe comparison; no subtraction overflow.
  • BY_MERITMarks high → low, ties broken by the natural order (roll).
  • BY_NAMECase-insensitive, so “zoya” doesn't jump after capitals.
8 Line by line

sort calls your compareTo

This trace is recorded from the real JVM. You never call compareTo yourself: watch Collections.sort call it on pairs of students (frames appear and disappear) and the list change order.

Worked examples: real problems, solved and traced in memory

Three sorting problems from real apps, using Comparable, a custom Comparator, and a comparator inside a PriorityQueue.

Example 1Railways · Comparable

Trains in departure order

Problem statement

A station display lists trains by departure time (HHMM as an int). Give Train a natural order by departure and sort three trains.

Input
12123 at 1715, 11007 at 0640, 12127 at 1015
Expected output
0640 11007
1015 12127
1715 12123

Approach

  1. Train implements Comparable<Train>; compareTo uses Integer.compare on departure.
  2. Collections.sort(list) needs no extra argument.
  3. Print the board.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 2Sales · Comparator

Leaderboard: revenue high to low, then name

Problem statement

Sales reps: Riya ₹80k, Om ₹95k, Kabir ₹80k. Sort by revenue (highest first); equal revenue by name. Write the comparator by hand as a class.

Input
Riya 80, Om 95, Kabir 80
Expected output
Om ₹95k
Kabir ₹80k
Riya ₹80k

Approach

  1. A class ByRevenue implements Comparator<Rep>.
  2. compare: compare revenues in reverse (Integer.compare(b, a)); if 0, compare names.
  3. list.sort(new ByRevenue()).

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 3Support · PriorityQueue

Serve the most urgent ticket first

Problem statement

Tickets have a severity (1 = critical) and an arrival number. Serve by severity, and for equal severity, by earlier arrival.

Input
(#1, sev 3), (#2, sev 1), (#3, sev 3), (#4, sev 1)
Expected output
#2 #4 #1 #3

Approach

  1. A PriorityQueue<int[]> with a comparator: severity first, then arrival.
  2. Offer all tickets.
  3. Poll until empty: always the most urgent, oldest first.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

9 Quiz and revision

Check yourself

Quick revision

Lesson 11.8 in one screen

  • Comparable (java.lang): compareTo(o) inside the class = one natural order.
  • Comparator (java.util): compare(a, b) outside = any number of orders, even for classes you can't edit.
  • Result sign: negative (before), 0 (same), positive (after).
  • Build comparators: comparing, comparingInt, thenComparing, reversed, nullsFirst/Last, naturalOrder, reverseOrder, String.CASE_INSENSITIVE_ORDER.
  • Use Integer.compare, never subtraction. Keep compareTo consistent with equals.
  • Used by Collections.sort, List.sort, Arrays.sort, TreeSet, TreeMap, PriorityQueue. Object sort = stable TimSort.

Interview and viva questions

Comparable vs Comparator: when do you use which?

Implement Comparable when the class has one obvious, natural order (ID, date, version). Use Comparators for every other order, for orders that depend on the situation (a screen's “sort by” choice), and for classes you don't own. Many classes have both: a natural order plus named comparators.

What does “consistent with equals” mean?

That compareTo returns 0 exactly when equals returns true. If not, sorted collections disagree with hash collections: a TreeSet may treat two unequal objects as duplicates, or keep two equal ones. BigDecimal is a famous exception: 2.0 and 2.00 compare as 0 but aren't equal.

Can you sort with a lambda?

Yes. Comparator is a functional interface, so list.sort((a, b) -> Integer.compare(a.marks, b.marks)) works, as does list.sort(Comparator.comparingInt(Student::marks)). Lambdas are covered in Lesson 14.1.

What is “Comparison method violates its general contract”?

TimSort throws this IllegalArgumentException when it detects an inconsistent comparator, e.g. one that isn't transitive, uses random values, or overflows with subtraction. Fix the comparator so it's a proper total order.

How do you sort in descending order?

list.sort(Comparator.reverseOrder()) for natural order, cmp.reversed() for a custom comparator, or Collections.sort(list, Collections.reverseOrder()).

Practice problems

Write natural orders and comparators, chain tie-breakers and avoid overflow. The last three are business tasks.

P1Easy

Sort numbers descending

Sort [5, 1, 9, 3] from highest to lowest.

Input
[5, 1, 9, 3]
Expected output
[9, 5, 3, 1]
Show solution and explanation
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<Integer> l = new ArrayList<>(List.of(5, 1, 9, 3));
        l.sort(Comparator.reverseOrder());
        System.out.println(l);
    }
}
[9, 5, 3, 1]

How it works: reverseOrder() flips Integer's natural order.

P2Easy

Sort words by length

Sort ["banana", "fig", "apple"] by length, shortest first.

Input
["banana", "fig", "apple"]
Expected output
[fig, apple, banana]
Show solution and explanation
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<String> w = new ArrayList<>(List.of("banana", "fig", "apple"));
        w.sort(Comparator.comparingInt(String::length));
        System.out.println(w);
    }
}
[fig, apple, banana]

How it works: comparingInt(String::length) builds a comparator from a key: the length of each word.

P3Easy

Comparable product by price

Make Product Comparable by price and sort three products.

Input
Pen 10, Bag 450, Book 120
Expected output
[Pen ₹10, Book ₹120, Bag ₹450]
Show solution and explanation
import java.util.*;

class Product implements Comparable<Product> {
    String name; int price;
    Product(String n, int p) { name = n; price = p; }
    public int compareTo(Product o) { return Integer.compare(price, o.price); }
    public String toString() { return name + " ₹" + price; }
}

public class Main {
    public static void main(String[] args) {
        List<Product> l = new ArrayList<>(List.of(new Product("Pen", 10), new Product("Bag", 450), new Product("Book", 120)));
        Collections.sort(l);
        System.out.println(l);
    }
}
[Pen ₹10, Book ₹120, Bag ₹450]

How it works: once the class is Comparable, Collections.sort needs no comparator.

P4Medium

Names: case-insensitive, then by length

Sort ["om", "Riya", "kabir", "Om"] case-insensitively; for equal names, shorter first, then natural order.

Input
["om", "Riya", "kabir", "Om"]
Expected output
[kabir, Om, om, Riya]
Show solution and explanation
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<String> n = new ArrayList<>(List.of("om", "Riya", "kabir", "Om"));
        n.sort(String.CASE_INSENSITIVE_ORDER.thenComparing(Comparator.naturalOrder()));
        System.out.println(n);
    }
}
[kabir, Om, om, Riya]

How it works: "om" and "Om" tie case-insensitively; the natural order then puts "Om" (capital O = 79) before "om" (111).

P5Medium

Nulls last

Sort ["b", null, "a"] with nulls at the end.

Input
["b", null, "a"]
Expected output
[a, b, null]
Show solution and explanation
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<String> l = new ArrayList<>(Arrays.asList("b", null, "a"));
        l.sort(Comparator.nullsLast(Comparator.naturalOrder()));
        System.out.println(l);
    }
}
[a, b, null]

How it works: without nullsLast, natural ordering would throw NullPointerException.

P6Business problem

Delivery route by pin, then time

Deliveries (pin, time): (410210, 14), (400703, 11), (410210, 9). Sort by pin, then by time.

Input
3 deliveries
Expected output
400703 at 11:00
410210 at 9:00
410210 at 14:00
Show solution and explanation
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<int[]> d = new ArrayList<>(List.of(new int[]{410210, 14}, new int[]{400703, 11}, new int[]{410210, 9}));
        d.sort(Comparator.<int[]>comparingInt(x -> x[0]).thenComparingInt(x -> x[1]));
        for (int[] x : d) System.out.println(x[0] + " at " + x[1] + ":00");
    }
}
400703 at 11:00 410210 at 9:00 410210 at 14:00

How it works: the second key only matters when the pins are equal. The <int[]> hint tells javac the element type for the lambdas.

P7Business problem

Top 2 rated restaurants

Restaurants with ratings: Chai Point 4.3, Dosa Hut 4.7, Vada Corner 4.5. Print the top 2 by rating.

Input
3 restaurants
Expected output
[Dosa Hut=4.7, Vada Corner=4.5]
Show solution and explanation
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Map<String, Double> rating = new HashMap<>(Map.of("Chai Point", 4.3, "Dosa Hut", 4.7, "Vada Corner", 4.5));
        List<Map.Entry<String, Double>> list = new ArrayList<>(rating.entrySet());
        list.sort(Map.Entry.<String, Double>comparingByValue().reversed());
        System.out.println(list.subList(0, 2));
    }
}
[Dosa Hut=4.7, Vada Corner=4.5]

How it works: map entries can be sorted with Map.Entry.comparingByValue(); reversed for highest first.

P8Business problem

Safe comparator for large amounts

Sort transaction amounts in paise [9_000_000_000L, -5L, 300L] ascending, safely.

Input
three long amounts
Expected output
[-5, 300, 9000000000]
Show solution and explanation
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<Long> paise = new ArrayList<>(List.of(9_000_000_000L, -5L, 300L));
        paise.sort(Long::compare);
        System.out.println(paise);
    }
}
[-5, 300, 9000000000]

How it works: Long.compare never overflows; a subtraction cast to int would give wrong signs for values this large.

Real-world scenario questions (asked in company interviews)

Sorting questions in interviews check whether your orders are correct, stable and maintainable.

E-commerce · bugJunior

Products jump between pages

Search results are sorted by price and shown 20 per page. Users report the same product appearing on page 1 and page 2, and some never appearing. Many products share the same price. What's wrong?

The interviewer is checking: tie-breakers and deterministic ordering.

Show a strong answer
  • Ties by price have no defined order, so each page request (often a separate database query) may order equal-priced products differently.
  • Add a unique tie-breaker: comparing(Product::price).thenComparing(Product::id) in Java, or ORDER BY price, id in SQL.
  • Now every request produces the same total order, so pages don't overlap.

Avoid: blaming caching. The order itself is ambiguous.

Fintech · correctnessJunior

Large transactions sorted wrongly

A report sorts transactions by amount in paise using (a, b) -> (int) (a.paise - b.paise). Small amounts sort fine; crore-rupee transfers appear in random places. Why?

The interviewer is checking: overflow and casting in comparators.

Show a strong answer
  • The difference of two large long values cast to int overflows, so the sign can be wrong.
  • Use Long.compare(a.paise, b.paise) or Comparator.comparingLong(Txn::paise).
  • Add a test with very large and negative values; a broken comparator can even make TimSort throw.

Avoid: converting to double; precision issues follow.

Sports · designFresher

Points table for a cricket league

Rank teams by points (high first); if equal, by net run rate (high first); if still equal, by team name. Write the comparator.

The interviewer is checking: multi-level comparators.

Show a strong answer
  • Comparator.comparingInt(Team::points).reversed().thenComparing(Comparator.comparingDouble(Team::nrr).reversed()).thenComparing(Team::name).
  • Note that reversed() on a chain reverses everything before it, so reverse each key's comparator separately, as above.
  • Keep it as a named constant (e.g. Team.TABLE_ORDER) and unit-test tie cases.

Avoid: a long hand-written if/else compare method; it's easy to get a branch wrong.

Platform · designMid

Should Order implement Comparable?

A teammate wants Order implements Comparable<Order> comparing by total amount, “because we often sort by amount”. Do you agree?

The interviewer is checking: what a natural order should be.

Show a strong answer
  • Amount isn't a natural, unique order: two different orders can have the same amount, so compareTo wouldn't be consistent with equals, and TreeSet<Order> would drop orders.
  • If anything, the natural order should be the unique order ID or creation time. Sorting by amount should be a named Comparator (Order.BY_AMOUNT).
  • This keeps sorted collections and reports correct and explicit.

Avoid: making the most frequently used sort the natural order just for convenience.