Java
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Java
-
Section 4: Collections Framework
-
Section 5: Exception Handling
-
Section 6: Generics
-
Section 7: Functional Java
-
Section 8: Concurrency
-
Section 9: I/O and NIO
-
Section 10: JVM Internals
-
Section 11: Modern Java Features
-
Section 12: Build Tools and Project Structure
-
Section 13: Testing
-
Section 14: Databases and Persistence
-
Section 15: Networking
-
Section 16: Design and Best Practices
-
Section 17: Reflection and Annotations
-
Section 18: Logging and Diagnostics
-
Section 19: Date, Time, and Internationalization
-
Section 20: Java Platform Module System
-
Section 21: Security in Java
-
Section 22: Advanced Collections and Data Structures
-
Section 23: More Concurrency Patterns
-
Section 24: Compression, Files, and System Integration
-
Section 25: GUI Programming
-
Section 26: Practical Projects
-
Section 27: Data Structures and Algorithms
-
Section 28: Interview and Algorithm Practice
-
Section 29: JSON and Data Interchange
-
Section 30: More Concurrency Utilities
-
Section 31: More Collections and Streams Practice
-
Section 32: More File and System Programming
-
Section 33: Standard Library Deep Dive
-
Section 34: More Practice and Drills
-
Section 35: More Testing and Quality
-
Section 36: More Design Patterns and Architecture
-
Section 37: Career and Ecosystem
-
Section 38: More OOP and Architecture Practice
-
Section 39: More Enterprise Concepts
-
Section 40: Advanced JavaFX
-
Section 41: More Interview Practice
49: Sorting Collections
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
Comparablein theCharacterclass; use aComparatorinstead. - Use
Comparator.comparingInt(...)and.thenComparing(...)to handle the tie-breaker logic. - Print the final sorted list to the console to verify the order.
There are no comments for now.