Tip: The following is the main content of this article, and the following cases are for reference
1. Comparable interface
Overview
Comparable is a generic interface that defines the natural ordering of objects. When you want the object of a class to be sorted, you can have the class implement the Comparable interface and override the compareTo method to specify the sorting rules.
method
int compareTo(T o):Compare the order of the current object to the specified object.
The return value is:
negative number:Indicates that the current object is smaller than the specified object.
zero:Indicates that two objects are equal.
Positive number:Indicates that the current object is larger than the specified object.
Suppose we have a Person class and we want to sort Person objects by age:
public class Person implements Comparable<Person> { private String name; private int age; public Person(String name, int age) { = name; = age; } @Override public int compareTo(Person other) { // Sort by ascending order of age return (, ); } @Override public String toString() { return "Person{name='" + name + "', age=" + age + '}'; } public static void main(String[] args) { List<Person> people = ( new Person("Alice", 30), new Person("Bob", 25), new Person("Charlie", 35) ); (people); // Use natural sorting (::println); } }
2. Comparator interface
Overview
The Comparator interface provides a flexible way to define sorting rules between objects without modifying the class itself. This is very useful for situations where you cannot modify the source code or require multiple sorting logic.
method
int compare(T o1, T o2):
Compare two objects to determine their order. The meaning of the return value is the same as the Comparable's compareTo method.
boolean equals(Object obj):Indicates whether this comparator is equal to the specified object. This method is not usually required unless there are special requirements.
In addition, starting with Java 8, the Comparator interface also provides default methods and static methods to simplify the creation and combination of comparators, such as:
default Comparator reversed():Returns a comparator in the opposite order of this comparator.
static <T, U extends Comparable<? super U>> Comparator comparing(Function<? super T, ? extends U> keyExtractor):Accepts a function that extracts the key and returns a comparator based on that key.
default Comparator thenComparing(Comparator<? super T> other):Add extra sorting conditions in chain.
Assuming we need to sort Person objects by name rather than age, we can define a Comparator:
import .*; public class Person { private String name; private int age; public Person(String name, int age) { = name; = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + '}'; } public static void main(String[] args) { List<Person> people = ( new Person("Alice", 30), new Person("Bob", 25), new Person("Charlie", 35) ); // Use custom Comparator Comparator<Person> byName = (p1, p2) -> ().compareTo(()); (byName); (::println); } }
The output will be a Person list arranged alphabetically by name.
3. Combined use
Sometimes you may need to combine Comparable and Comparator to implement more complex sorting logic. For example, sort in descending order of age, and then sort in ascending order of names if the age is the same:
import .*; import ; public class Person implements Comparable<Person> { private String name; private int age; public Person(String name, int age) { = name; = age; } @Override public int compareTo(Person other) { // Sort by ascending age by default return (, ); } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + '}'; } public static void main(String[] args) { List<Person> people = ( new Person("Alice", 30), new Person("Bob", 25), new Person("Charlie", 35), new Person("David", 30) ); // Sort by descending age first, then ascending order by name ((Person::getAge).reversed() .thenComparing(Person::getName)); (::println); } }
In this example, we first create a comparator sorted by descending age via (Person::getAge).reversed() , and then add a secondary sorting condition via .thenComparing(Person::getName) , that is, sort by ascending name under the same age.
4. Basic types of packaging classes and their comparison methods
In fact, for comparisons of basic data types, Java provides corresponding wrapper classes, and each has a similar static compare method. In addition, some collection types in the standard library (such as TreeSet, TreeMap) use Comparator for comparison of elements, but they do not implement the compare method by themselves.
Basic types of packaging classes and their comparison methods
The wrapper classes corresponding to the basic types of Java provide static compare methods to compare two values of the corresponding types:
Integer
static int compare(int x, int y)
Long
static int compare(long x, long y)
Float
static int compare(float f1, float f2)
Double
static int compare(double d1, double d2)
Short
static int compare(short s1, short s2)
Byte
static int compare(byte b1, byte b2)
Character
static int compare(char x, char y)
Boolean
There is no direct comparison method, because Booleans only have two states (true and false), which can be compared directly through logical operators.
These methods simplify comparison operations between basic types and avoid writing comparison logic manually (such as avoiding the overflow problems that can result from direct use of subtraction).
Comparison in collection framework
Although wrapper classes of basic types provide a comparison method, in the collection framework, it is more common to use the Comparator interface or have element types implement the Comparable interface for custom sorting. Here are some related collection types:
TreeSet:
An ordered collection that either requires its elements to implement the Comparable interface or provide a Comparator at creation time.
TreeMap:
A key-value pair mapping table where keys remain ordered. Likewise, it also requires that keys implement Comparable or provide a Comparator when constructed.
PriorityQueue:
A priority queue, based on natural order by default (if the elements implement Comparable), can also specify a Comparator at creation time.
import ; import ; public class Main { public static void main(String[] args) { TreeSet<Integer> numbers = new TreeSet<>(()); // Use the reverse order comparator (1); (2); (3); (numbers); // Output [3, 2, 1] } }
Summarize
Comparable:It is suitable for defining natural sorting rules for classes, requiring classes to implement Comparable interfaces, and override the compareTo method.
Comparator:Provides greater flexibility, allowing you to define different sorting rules without modifying the class. Comparators can be created through anonymous inner classes, lambda expressions, or method references, and multiple comparison conditions are supported in chain calls.
Which method to choose depends on the specific application scenario. Comparable may be more appropriate if you only need a fixed sorting method; if you need multiple sorting methods or cannot modify the original class, you should use Comparator.
This is the article about how to use JAVA Comparator and Comparable interfaces. For more related contents of java comparator and comparable interfaces, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!