compareTo and how does it work?compareTo work with Strings?compareTo work the same way for numbers?compareTo with custom objectscompareTocompareTo 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); // falseBut 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 compareTocomes 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: 50So what’s happening here?
Well, Java calls compareTo on each pair of players:
Alice.compareTo(Bob) → Integer.compare(75, 50) → returns 1Charlie.compareTo(Bob) → Integer.compare(75, 60) → returns 1Charlie.compareTo(Alice) → Integer.compare(60, 50) → returns -1Once 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)); // -1Just like before:
compareTo returns -101< 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); // ERRORSince 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 other0) → They are equal1) → this is greater than otherHow 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;
}compareToTo 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.
