Skip to Content
Course content

49: Sorting Collections

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've been working on a small project—a basic task manager—and I've hit a wall. I have a List of Task objects, and right now, they're just in the order I added them. That's useless. I need them sorted by priority so I know what to work on first.

class Task {
    String title;
    int priority;

    Task(String title, int priority) {
        this.title = title;
        this.priority = priority;
    }

    @Override
    public String toString() {
        return priority + ": " + title;
    }
}

The "Wait, Why Did it Crash?" Moment

My first instinct was to just use Collections.sort(). It's the standard tool, right? I set up a list, added a few tasks, and called the sort method. Here is what happened:

List<Task> tasks = new ArrayList<>();
tasks.add(new Task("Fix login bug", 2));
tasks.add(new Task("Write docs", 3));
tasks.add(new Task("Update server", 1));

Collections.sort(tasks); // Boom. ClassCastException.

Java threw a ClassCastException telling me that Task cannot be cast to Comparable. It makes sense when you think about it: Java knows how to sort Integers or Strings because those classes have a natural order. But what is the "natural order" of a Task? Is it alphabetical by title? Is it by priority? Java isn't a mind reader; I have to tell it how to decide which task comes first.

Teaching the Class to Compare Itself

The quickest fix is to make the Task class implement the Comparable interface. This basically tells Java, "Whenever you see a Task, here is the logic you should use to compare it to another Task."

class Task implements Comparable<Task> {
    String title;
    int priority;

    // ... constructor and toString ...

    @Override
    public int compareTo(Task other) {
        // I want lower numbers to be higher priority (1 comes before 3)
        return Integer.compare(this.priority, other.priority);
    }
}

I tried running the Collections.sort(tasks) call again, and it worked perfectly. The list is now [1: Update server, 2: Fix login bug, 3: Write docs]. But here is the problem: I just realized I might want to sort by the title alphabetically for a different view in my app. If I change the compareTo method, I break the priority sorting. I can't have it both ways inside the class itself.

Breaking Away from the "Natural Order"

This is where Comparator comes in. Instead of the object knowing how to sort itself, I can create a separate "judge" that decides the order for me. This is way more flexible because I can have as many different comparators as I want.

At first, I wrote a whole separate class for this, but that's too much boilerplate. Since we're using modern Java, I'll just use a lambda expression directly inside the sort method:

// Sort by title instead of priority
Collections.sort(tasks, (t1, t2) -> t1.title.compareTo(t2.title));

Wait, there's an even cleaner way. Java added some helper methods to the Comparator interface that make this read like a sentence. Instead of the lambda, I can do this:

import java.util.Comparator;

tasks.sort(Comparator.comparingInt(t -> t.priority));

I prefer this. It's concise, and it avoids the manual integer comparison logic. If I wanted to reverse it (highest priority number first), I'd just tack .reversed() onto the end of that comparator chain. It's much more intuitive than flipping the subtraction logic in a compareTo method.




📋 Practical Task

The RPG Character Leaderboard Sorter

You are building a leaderboard for an RPG game. You have a Character class with two fields: String name and int level.

Your Goal: Create a list of at least five Character objects. Your task is to sort this list using a Comparator so that the characters are ordered by level in descending order (highest level first). If two characters have the same level, they should be sorted alphabetically by name.

Requirements:

  • Do not implement Comparable in the Character class; use a Comparator instead.
  • Use Comparator.comparingInt(...) and .thenComparing(...) to handle the tie-breaker logic.
  • Print the final sorted list to the console to verify the order.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.