compareTo
and how does it work?compareTo
work with Strings?compareTo
work the same way for numbers?compareTo
with custom objectscompareTo
compareTo
into practiceComparing numbers in Java is simple. You can just use <
, >
, or ==
.
But what if you need to compare objects, like sorting names alphabetically or ranking players by score? Java doesn’t let you use <
or >
on objects, so how do you figure out which one comes first?
That’s where compareTo
comes in. It’s Java’s built-in method for comparing objects, helping you sort lists, rank values, and organize data the way you want.
But if you’ve never used it before, it might seem a little weird. Why does it return -1
, 0
, or 1
instead of true
or false
?
Don’t worry because we’ll cover all that and more, so that by the end of this guide, you’ll not only understand how compareTo
works - you’ll be confident using it to compare strings, numbers, and even custom objects. Ready to see it in action?
Let’s go!
Sidenote: If you find that you’re struggling with the content in this guide, or perhaps feel that you could use some more training, or simply want to build some more impressive projects for your portfolio, then check out my Java programming bootcamp:
Updated for 2025, you'll learn Java programming fundamentals all the way from complete beginner to advanced skills.
Better still, you’ll be able to reinforce your learning with over 80 exercises and 18 quizzes. This is the only course you need to go from complete programming beginner to being able to get hired as a Backend Developer!
With that out of the way, let’s get into these interview questions!
At some point in your coding career, you'll need to compare things in Java.
Maybe you're sorting a list, checking if one number is bigger than another, or figuring out if two values are the same. If you're working with numbers like int
or double
, comparisons are easy:
int a = 5;
int b = 10;
System.out.println(a < b); // true
System.out.println(a > b); // false
System.out.println(a == b); // false
But what if you're working with objects like String
or Integer
?
Unlike numbers, Java doesn't allow direct comparisons using <
or >
because objects don’t have a built-in way to determine which one is "greater" or "smaller." That’s where compareTo
comes in.
Java uses compareTo
to decide how objects should be ordered:
-1
→ The first value comes before the second0
→ The two values are equal1
→ The first value comes after the secondSince sorting isn’t just about knowing whether two values are different - but rather how they should be arranged — Java repeatedly calls compareTo
to position elements correctly in a list. This allows it to sort objects automatically, without requiring custom logic each time.
For example
Imagine you’re building a leaderboard for a game. You have a list of players, and you need to rank them based on their scores.
The problem? Java doesn’t automatically know how to order them and so you have to define the logic. Here’s how you can use compareTo
to sort players by score:
class Player implements Comparable<Player> {
String name;
int score;
public Player(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int compareTo(Player other) {
return Integer.compare(other.score, this.score); // Higher scores come first
}
}
Now, let’s sort a list of players:
import java.util.*;
public class Leaderboard {
public static void main(String[] args) {
List<Player> players = new ArrayList<>();
players.add(new Player("Alice", 50));
players.add(new Player("Bob", 75));
players.add(new Player("Charlie", 60));
Collections.sort(players); // Uses compareTo()
for (Player p : players) {
System.out.println(p.name + ": " + p.score);
}
}
}
Expected output:
Bob: 75
Charlie: 60
Alice: 50
So what’s happening here?
Well, Java calls compareTo
on each pair of players:
Alice.compareTo(Bob)
→ Integer.compare(75, 50)
→ returns 1
Charlie.compareTo(Bob)
→ Integer.compare(75, 60)
→ returns 1
Charlie.compareTo(Alice)
→ Integer.compare(60, 50)
→ returns -1
Once all comparisons are made, Java arranges the list based on these return values.
Every call to compareTo
tells Java how to position elements in the list:
-1
moves an item up in the list1
moves it down0
keeps it in placeSorting algorithms rely on these return values to organize lists automatically.
Now that you’ve seen how compareTo
works with custom objects, let’s see how Java uses it for built-in types like String
and Integer
.
You probably compare strings all the time — checking if two names are the same or sorting a list alphabetically. But how does Java actually do it?
Java uses compareTo
to compare strings letter by letter based on their Unicode values. That means it follows the same order you’d expect in a dictionary.
For example
public class CompareStrings {
public static void main(String[] args) {
String name1 = "Alice";
String name2 = "Bob";
int result = name1.compareTo(name2);
System.out.println(result);
}
}
Java looks at "Alice"
and "Bob"
and checks the first letter of each:
'A'
comes before 'B'
, so "Alice".compareTo("Bob")
returns a negative number (-1
)"Bob".compareTo("Alice")
), it would return a positive number (1
)Simple enough right? But what if the first letters are the same? Heck, what if the names are almost identical?
For example
Let’s try comparing "Alice"
and "Alicia"
:
public class CompareStrings {
public static void main(String[] args) {
String name1 = "Alice";
String name2 = "Alicia";
int result = name1.compareTo(name2);
System.out.println(result);
}
}
Since "Alice"
and "Alicia"
start with the same five letters, Java keeps going until it finds a difference. It gets to 'e'
in "Alice"
and 'i'
in "Alicia"
, and since 'e'
comes before 'i'
, Java returns -1
— meaning "Alice"
comes first.
However, if the words were exactly the same ("Alice".compareTo("Alice")
), compareTo
would return 0
, because there’s nothing to compare!
So the next time you sort a list of names, remember — Java is just running compareTo
behind the scenes, checking letters one by one.
Speaking of sorting, numbers work in a similar way. Let’s check that out next.
Since compareTo
sorts Strings alphabetically by checking each letter, you might wonder if it does the same thing for numbers?
The answer is yes, but it’s much simpler. Instead of checking letters, Java compares the actual values:
Integer num1 = 5;
Integer num2 = 10;
System.out.println(num1.compareTo(num2)); // -1
Just like before:
compareTo
returns -1
0
1
<
and >
?If you’re working with primitive types you can just use <
and >
. But with objects like Integer
and Double
, Java doesn’t allow direct comparisons:
Integer num1 = 5;
Integer num2 = 10;
System.out.println(num1 < num2); // ERROR
Since Integer
is an object, you have to use compareTo
instead.
(Most of the time, you won’t need it — but when sorting numbers in a list or working with BigDecimal
, compareTo
is essential).
Now that we’ve seen how compareTo
works with Strings and numbers, let’s talk about sorting custom objects. Java already knows how to compare built-in types, but what happens when you need to sort objects of your own?
Unlike built-in types like String
or Integer
, Java doesn’t know how to compare custom objects— unless you explicitly tell it how. That’s where Comparable<T>
comes in.
To make your objects sortable, your class needs to implement the Comparable<T>
interface and define a compareTo
method.
class Person implements Comparable<Person> {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age); // Sort by age
}
}
Now, Java understands how to compare two Person
objects based on their age
. This allows them to be sorted automatically using Collections.sort()
:
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 20));
people.add(new Person("Alice", 25));
people.add(new Person("Bob", 30));
Collections.sort(people); // Works because Person implements Comparable<Person>
Why does Comparable<T>
matter?
Collections.sort()
without extra codecompareTo
does the work automaticallyNow that we know how to make a class comparable, let’s apply it in a real-world scenario.
Let’s say you’re building a user management system, and you want to store a list of users sorted by age.
The problem? Java doesn’t automatically know how to compare two Person
objects. Unlike numbers, objects don’t have a built-in way to determine which one is "greater" or "smaller."
That’s why Java requires you to explicitly define how objects should be compared using compareTo
. But what should we compare? Names? Ages? There’s no default answer — you decide what makes sense for your use case.
Here’s how to define sorting logic for a Person
class by age:
class Person implements Comparable<Person> {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age); // Sort by age
}
}
Now, Java understands how to compare two Person
objects based on their age. This allows them to be sorted automatically using Collections.sort()
:
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 20));
people.add(new Person("Alice", 25));
people.add(new Person("Bob", 30));
Collections.sort(people); // Works because Person implements Comparable<Person>
Without compareTo
, Java wouldn’t know how to order custom objects in a list. But how does this actually work behind the scenes? Let’s break it down and see how to make objects sortable.
Unlike built-in types like String
or Integer
, Java has no built-in way to compare custom objects — unless you define the rules yourself.
And so to make your objects sortable, you need to tell Java how to compare them by implementing the Comparable<T>
interface and define a compareTo
method.
For example
Here’s how to define sorting logic for a Person
class by age:
class Person implements Comparable<Person> {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
}
Now, Java understands how to compare two Person
objects based on their age. This allows them to be sorted automatically using Collections.sort()
.
Let’s test this:
public class ComparePeople {
public static void main(String[] args) {
Person alice = new Person("Alice", 25);
Person bob = new Person("Bob", 30);
System.out.println(alice.compareTo(bob)); // -1 (Alice is younger than Bob)
System.out.println(bob.compareTo(alice)); // 1 (Bob is older than Alice)
}
}
Since compareTo
defines the ranking, Java can now sort Person
objects automatically.
import java.util.*;
public class ComparePeople {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 20));
people.add(new Person("Alice", 25));
people.add(new Person("Bob", 30));
Collections.sort(people); // Sorts by age because of compareTo()
for (Person person : people) {
System.out.println(person.name + " (" + person.age + ")");
}
}
}
Output:
Charlie (20)
Alice (25)
Bob (30)
Since compareTo
defines how Person
objects should be ranked, Java can automatically sort them in the correct order.
Why does this matter?
Without compareTo
, sorting custom objects would be a hassle. You’d have to manually write sorting logic every time you needed to order a list.
Think about other objects you might need to compare:
Product
objects by priceEmployee
records by salaryPlayer
objects by scoreInstead of re-writing sorting logic every time, implementing compareTo
makes objects sortable everywhere, saving time and keeping your code clean.
Handy right?
But of course there is a catch in that small mistakes in how you implement compareTo
can lead to weird sorting behavior, hard-to-debug errors, or even crashes.
So, before you start using it everywhere, let’s go over some common pitfalls and best practices to make sure your comparisons are rock solid.
0
return value)Imagine you’re sorting a list of Person
objects by age. You write a compareTo
method like this:
@Override
public int compareTo(Person other) {
return this.age - other.age;
}
At first glance, it looks fine because it returns a negative number if this.age
is smaller and a positive number if it's larger.
Why is this a problem?
If two objects have the same age, this.age - other.age
results in 0
, which means they are equal. That’s not a problem by itself, but this approach has two major issues:
this.age
is a very large number and other.age
is a very small number, subtracting them could cause integer overflow, leading to unexpected resultsHow to fix it
Instead of subtracting values, use Integer.compare()
, which is built to handle comparisons safely.
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
Why is this better?
0
return)Beginners sometimes write compareTo
backward, which completely reverses the sorting order.
Incorrect approach:
@Override
public int compareTo(Person other) {
if (this.age < other.age) return 1; // Wrong: should return -1
if (this.age > other.age) return -1; // Wrong: should return 1
return 0;
}
Why does this happen?
It’s easy to assume that higher numbers should come first and accidentally flip the logic. But compareTo
follows a strict convention:
-1
) → this
is smaller than other
0
) → They are equal1
) → this
is greater than other
How to fix it
Always follow standard ordering:
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
Need to reverse the order? Instead of flipping compareTo
, sort with Collections.reverseOrder()
:
Collections.sort(people, Collections.reverseOrder());
Comparable<T>
Sometimes, developers write a compareTo
method but forget to declare that the class implements Comparable<T>
:
Incorrect approach:
class Person {
String name;
int age;
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
}
Why is this a problem?
compareTo
as an official methodCollections.sort()
compareTo()
How to fix it
Always declare implements Comparable<T>
:
class Person implements Comparable<Person> {
String name;
int age;
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
}
This tells Java that Person
objects can be compared, allowing sorting and comparisons to work properly.
Sometimes, you need to compare objects by more than one field. For example, if two people are the same age, you might want to sort them alphabetically by name.
Incorrect approach:
@Override
public int compareTo(Person other) {
return this.age - other.age + this.name.compareTo(other.name);
}
Why is this a problem?
this.age - other.age
produces a single number, adding the name comparison could cause wrong resultsthis.age - other.age
can cause overflow issuesHow to fix it
Instead of adding values, compare the fields separately:
@Override
public int compareTo(Person other) {
int ageComparison = Integer.compare(this.age, other.age);
if (ageComparison == 0) {
return this.name.compareTo(other.name); // Compare by name if ages are the same
}
return ageComparison;
}
@Override
public int compareTo(Person other) {
int ageComparison = Integer.compare(this.age, other.age);
if (ageComparison == 0) {
return this.name.compareTo(other.name); // Compare by name if ages are the same
}
return ageComparison;
}
compareTo
consistent with equals()
If two objects are considered equal by .equals()
, they must return 0
in compareTo
. Otherwise, sorting and collections won’t behave correctly.
Incorrect approach:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Person)) return false;
Person other = (Person) obj;
return this.name.equals(other.name);
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age); // Ignores name comparison
}
Why is this a problem?
.equals()
says two people are equal if their names match, but compareTo
only checks ageHow to fix it
Ensure compareTo
respects equality rules:
@Override
public int compareTo(Person other) {
int nameComparison = this.name.compareTo(other.name);
if (nameComparison == 0) {
return Integer.compare(this.age, other.age);
}
return nameComparison;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Person)) return false;
Person other = (Person) obj;
return this.name.equals(other.name) && this.age == other.age;
}
compareTo
To avoid common pitfalls, follow these best practices:
Integer.compare()
instead of this.age - other.age
to prevent integer overflowcompareTo
consistent with equals()
to avoid sorting inconsistenciesComparator
when you need multiple sorting options instead of modifying compareTo()
By following these, you’ll ensure that your comparisons are accurate, stable, and efficient.
Now that you understand how compareTo
works, the best way to master it is to try it yourself. Create your own classes, implement Comparable<T>
, and experiment with sorting different objects.
Test edge cases, tweak comparison logic, and see how small changes affect sorting. The more you practice, the more intuitive it will become.
So go ahead — write some code, sort some objects, and make Java do the work for you!
Remember, if you want to fast-track your Java knowledge and get as much hands-on practice as possible, then check out my Java programming bootcamp:
Updated for 2025, you'll learn Java programming fundamentals all the way from complete beginner to advanced skills.
Better still, you’ll be able to reinforce your learning with over 80 exercises and 18 quizzes. This is the only course you need to go from complete programming beginner to being able to get hired as a Backend Developer!
Plus, once you join, you'll have the opportunity to ask questions in our private Discord community from me, other students and working DevOps professionals.