Comparable
Comparable is the sorting interface.
If a class implements the Comparable interface, it means "this class supports sorting". Since classes that implement Comparable interface support sorting, assuming that there is now a "List list (or array) of objects of classes that implement Comparable interface", the List list (or array) can be sorted by Collections.sort (or Arrays.sort).
In addition, "Object of the class that implements Comparable interface" can be used as a key in a "ordered map (such as TreeMap)" or an element in a "ordered set (TreeSet)" without specifying a comparator.
The Comparable interface only includes one function, and its definition is as follows:
package java.lang;import java.util.*;public interface Comparable<T> { public int compareTo(T o);} Description: Suppose we "compare the sizes of x and y" through x.compareTo(y). If you return a "negative number", it means "x is smaller than y"; if you return a "zero", it means "x is equal to y"; if you return a "positive number", it means "x is greater than y".
The Comparable interface has been generic, so the object that implements Comparable declares what type it can be compared with. (Generally, this is the type of the object itself, but it may also be a parent class sometimes.)
public interface Comparable { public boolean compareTo(T other); }
Therefore, the Comparable interface contains a type parameter T, which is the type of an object that a class that implements Comparable can compare with. This means that if you define a class that implements Comparable, such as String, you must declare not only the class supports comparison, but also what it can compare to (usually to itself):
public class String implements Comparable { ... }
Now let’s consider the implementation of a binary max() method. You want to accept two parameters of the same type, both are Comparable and are Comparable to each other. Fortunately, this is quite intuitive if you use generic methods and restricted type parameters:
public static > T max(T t1, T t2) { if (t1.compareTo(t2) > 0) return t1; else return t2; }
In this example, you define a generic method that is generified on type T, and you constrain the type extension (implementation) Comparable. Both parameters must be of type T, which means they are of the same type, support comparison, and are comparable to each other. easy!
Even better, the compiler will use type reasoning to determine what the value of T means when max() is called. So there is no need to specify T at all, the following call will work:
String s = max("moo", "bark");The compiler will calculate that the predetermined value of T is String, so it will perform compilation and type checking. But if you try to call max() with arguments to class X that does not implement Comparable, the compiler will not allow this.
Comparator
Comparator is the comparator interface.
If we need to control the order of a certain class, which itself does not support sorting (that is, it does not implement the Comparable interface); then we can establish a "comparator of this class" to sort. This "comparator" only needs to implement the Comparator interface.
That is, we can create a new comparator by "implementing the Comparator class", and then sort the class through the comparator.
The Comparator interface only includes two functions, and its definition is as follows:
package java.util;public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj);} illustrate:
1. If a class wants to implement the Comparator interface: it must implement the compareTo(T o1, T o2) function, but it may not implement the equals(Object obj) function.
Why can we not implement the equals(Object obj) function? Because by default, equals(Object obj) has been implemented. All classes in Java are inherited from java.lang.Object, and the equals(Object obj) function is implemented in Object.java; therefore, all other classes are equivalent to implementing this function.
2.int compare(T o1, T o2) is "compare the sizes of o1 and o2". Returning "negative number" means "o1 is smaller than o2"; returning "zero", meaning "o1 is equal to o2"; returning "positive number" means "o1 is greater than o2".
Comparator and Comparable
Comparable is a sorting interface; if a class implements a Comparable interface, it means "this class supports sorting".
Comparator is a comparator; if we need to control the order of a certain class, we can establish a "comparator of this class" to sort it.
It is not difficult to find that Comparable is equivalent to an "internal comparator", while Comparator is equivalent to an "external comparator".
We use a test program to illustrate these two interfaces. The source code is as follows:
import java.util.*;import java.lang.Comparable;/** * @desc Comparison program between "Comparator" and "Comparable". * (01) "Comparable" * It is a sorting interface that contains only one function compareTo(). * A class implements the Comparable interface, which means "the class itself supports sorting", which can be sorted directly through Arrays.sort() or Collections.sort(). * (02) "Comparator" * It is a comparator interface, including two functions: compare() and equals(). * A class implements the Comparator interface, then it is a "comparator". Other classes can be sorted according to the comparator. * * To sum up: Comparable is an internal comparator, while Comparator is an external comparator. * A class itself implements a Comparable comparator, which means that it supports sorting; if it does not implement Comparable itself, it can also be sorted through the external comparator Comparator. */public class CompareComparatorAndComparableTest{ public static void main(String[] args) { // Create a new ArrayList(dynamic array) ArrayList<Person> list = new ArrayList<Person>(); // Add an object to ArrayList list.add(new Person("ccc", 20)); list.add(new Person("AAA", 30)); list.add(new Person("bbb", 10)); list.add(new Person("ddd", 40)); // Print the original sequence of the list System.out.printf("Original sort, list:%s/n", list); // Sort the list// Here it will be sorted according to the "Comparable<String> interface implemented by Person", that is, sorted according to "name", Collections.sort(list); System.out.printf("Name sort, list:%s/n", list); // Sort the list through "Comparator (AscAgeComparator)" // The sorting method of AscAgeComparator is: sorted according to the ascending order of "age" Collections.sort(list, new AscAgeComparator()); System.out.printf("Asc(age) sort, list:%s/n", list); // Sort the list through "Comparator (DescAgeComparator)". // The sorting method of DescAgeComparator is: sort according to descending order of "age" Collections.sort(list, new DescAgeComparator()); System.out.printf("Desc(age) sort, list:%s/n", list); // Determine whether the two persons are equal testEquals(); } /** * @desc Test whether the two Persons are equal. * Since Person implements the equals() function: if the age and name of the two persons are equal, the two persons are considered to be equal. * So, here p1 and p2 are equal. * * TODO: If the equals() function in Person is removed, then p1 does not equal p2 */ private static void testEquals() { Person p1 = new Person("eee", 100); Person p2 = new Person("eee", 100); if (p1.equals(p2)) { System.out.printf("%s EQUAL %s/n", p1, p2); } else { System.out.printf("%s NOT EQUAL %s/n", p1, p2); } } /** * @desc Person class. * Person implements the Comparable interface, which means that Person itself supports sorting*/ private static class Person implements Comparable<Person>{ int age; String name; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public String toString() { return name + " - " +age; } /** * Compare whether two Persons are equal: if their name and age are equal, they are considered equal*/ boolean equals(Person person) { if (this.age == person.age && this.name == person.name) return true; return false; } /** * @desc Implement the interface of "Comparable<String>", that is, rewrite the compareTo<T t> function. * Here is a comparison by "person's name"*/ @Override public int compareTo(Person person) { return name.compareTo(person.name); //return this.name - person.name; } } /** * @desc AscAgeComparator comparator* It is "ascending comparator of Person's age" */ private static class AscAgeComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p1.getAge() - p2.getAge(); } } /** * @desc DescAgeComparator comparator* It is "ascending comparator of Person's age" */ private static class DescAgeComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p2.getAge() - p1.getAge(); } }} The following is an explanation of this program.
1.Person class definition. as follows:
private static class Person implements Comparable<Person>{ int age; String name; ... /** * @desc Implements the interface of "Comparable<String>", that is, override the compareTo<T t> function. * Here is a comparison by "person's name"*/ @Override public int compareTo(Person person) { return name.compareTo(person.name); //return this.name - person.name; } } illustrate:
(1) The Person class represents a person. There are two attributes in the Persong class: age (age) and name "person name".
(2) The Person class implements the Comparable interface, so it can be sorted.
2. In main(), we create Person's List array (list). as follows:
// Create a new ArrayList(dynamic array)ArrayList<Person> list = new ArrayList<Person>();// Add an object to ArrayList list.add(new Person("ccc", 20));list.add(new Person("AAA", 30));list.add(new Person("bbb", 10));list.add(new Person("ddd", 40)); 3. Next, we print out all the elements of the list. as follows:
// Print the original sequence of list System.out.printf("Original sort, list:%s/n", list); 4. Then, we sort the list through the sort() function of Collections.
Since Person implements the Comparable interface, when sorting through sort(), it will be sorted according to the sort method supported by Person, that is, the rules defined by compareTo(Person person). as follows:
// Sort the list// Here we will sort according to the "Comparable<String> interface implemented by Person", that is, sorting according to "name" Collections.sort(list); System.out.printf("Name sort, list:%s/n", list); 5. Comparable and Comparator
We define two comparators, AscAgeComparator and DescAgeComparator, to ascend and lower order Person respectively.
6.AscAgeComparator Comparator It sorts Person in ascending order by age. The code is as follows:
/** * @desc AscAgeComparator comparator* It is "ascending comparator of Person's age" */private static class AscAgeComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p1.getAge() - p2.getAge(); }} 7.DescAgeComparator Comparator It sorts Person in descending order by age. The code is as follows:
/** * @desc DescAgeComparator comparator* It is "ascending comparator of Person's age" */private static class DescAgeComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p2.getAge() - p1.getAge(); }} 8. Run the program as a result, the output is as follows:
Original sort, list:[ccc - 20, AAA - 30, bbb - 10, ddd - 40]Name sort, list:[AAA - 30, bbb - 10, ccc - 20, ddd - 40]Asc(age) sort, list:[bbb - 10, ccc - 20, AAA - 30, ddd - 40]Desc(age) sort, list:[ddd - 40, AAA - 30, ccc - 20, bbb - 10]eee - 100 EQUAL eee - 100