This article brings you a comparative introduction (code example) about Comparable and Comparator in Java. It has certain reference value. Friends in need can refer to it. Hope it helps.
1. Overview
Sorting in Java is provided by the two interfaces Comparable and Comparator.
Comparable means that it can be sorted, and objects of classes that implement this interface automatically have the sorting function.
Comparator represents a comparator. The object of the class that implements this interface is a comparator defined for the object of the target class. Generally, this comparator will be passed as a parameter.
2. Comparable
The Chinese meaning of Comparable is that it can be sorted, which means it supports the sorting function. As long as our class implements this interface, objects of this class will automatically have the ability to be sorted. And this ordering is called the natural order of classes. Lists of objects of this class can be sorted by Collections.sort and Arrays.sort. At the same time, instances of this class are qualified as keys of sorted map and elements of sorted set.
If a and b are both instances of class C that implements the Comparable interface, then only when the result of a.compareTo(b) is consistent with the result of a.equals(b), it is called class C. The natural order is consistent with equals. It is strongly recommended to keep the natural order of the class consistent with the result of equals, because if they are inconsistent, the behavior of a sorted map with objects of this class as keys and a sorted set with objects of this class as elements will behave weirdly.
For example, for a sorted set that implements the Comparable interface, if the result of a.equals(b) is false and a.compareTo(b)==0, then the second The addition operation of elements will fail, because in the eyes of sorted set, the two are consistent in sorting, and it does not save duplicate elements.
In fact, the natural order of classes in Java is basically consistent with equals, except for BigDecimal, because the natural order in BigDecimal is consistent with the equals of elements with the same value but different precision (such as 4 and 4.00) .
public interface Comparable<T> { public int compareTo(T o); }
It can be seen from the source code that the interface has only one abstract method compareTo. This method is mainly to define the way our classes are sorted. The compareTo method is used to compare the current element a with the specified element b. The result is an int value. If a > b, int > 0; if a = b, int = 0; if a < b, int < 0.
3. Comparator
Comparator is translated as comparator in Chinese. It can be passed as a parameter to the Collections.sort and Arrays.sort methods to specify a certain class object. sort by. At the same time, it can also specify the sorting method for sorted set and sorted map.
Similar to Comparable, when specifying a comparator, it is generally necessary to ensure that the comparison result is consistent with the equals result. If they are inconsistent, the behavior of the corresponding sorted set and sorted map will also become weird.
It is recommended that the implemented comparator class also implements the java.io.Serializable interface to have serialization capabilities, because it may be used as a sorting method for serialized data structures (TreeSet, TreeMap).
@FunctionalInterface public interface Comparator<T> { // 唯一的抽象方法,用于定义比较方式(即排序方式) // o1>o2,返回1;o1=o2,返回0;o1<o2,返回-1 int compare(T o1, T o2); boolean equals(Object obj); // 1.8新增的默认方法:用于反序排列 default Comparator<T> reversed() { return Collections.reverseOrder(this); } // 1.8新增的默认方法:用于构建一个次级比较器,当前比较器比较结果为0,则使用次级比较器比较 default Comparator<T> thenComparing(Comparator<? super T> other) { Objects.requireNonNull(other); return (Comparator<T> & Serializable) (c1, c2) -> { int res = compare(c1, c2); return (res != 0) ? res : other.compare(c1, c2); }; } // 1.8新增默认方法:指定次级比较器的 // keyExtractor表示键提取器,定义提取方式 // keyComparator表示键比较器,定义比较方式 default <U> Comparator<T> thenComparing( Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) { return thenComparing(comparing(keyExtractor, keyComparator)); } // 1.8新增默认方法:用于执行键的比较,采用的是由键对象内置的比较方式 default <U extends Comparable<? super U>> Comparator<T> thenComparing( Function<? super T, ? extends U> keyExtractor) { return thenComparing(comparing(keyExtractor)); } // 1.8新增默认方法:用于比较执行int类型的键的比较 default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) { return thenComparing(comparingInt(keyExtractor)); } // 1.8新增默认方法:用于比较执行long类型的键的比较 default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) { return thenComparing(comparingLong(keyExtractor)); } // 1.8新增默认方法:用于比较执行double类型的键的比较 default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) { return thenComparing(comparingDouble(keyExtractor)); } // 1.8新增静态方法:用于得到一个相反的排序的比较器,这里针对的是内置的排序方式(即继承Comparable) public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return Collections.reverseOrder(); } // 1.8新增静态方法:用于得到一个实现了Comparable接口的类的比较方式的比较器 // 简言之就是将Comparable定义的比较方式使用Comparator实现 @SuppressWarnings("unchecked") public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE; } // 1.8新增静态方法:得到一个null亲和的比较器,null小于非null,两个null相等,如果全不是null, // 则使用指定的比较器比较,若未指定比较器,则非null全部相等返回0 public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) { return new Comparators.NullComparator<>(true, comparator); } // 1.8新增静态方法:得到一个null亲和的比较器,null大于非null,两个null相等,如果全不是null, // 则使用指定的比较器比较,若未指定比较器,则非null全部相等返回0 public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) { return new Comparators.NullComparator<>(false, comparator); } // 1.8新增静态方法:使用指定的键比较器用于执行键的比较 public static <T, U> Comparator<T> comparing( Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) { Objects.requireNonNull(keyExtractor); Objects.requireNonNull(keyComparator); return (Comparator<T> & Serializable) (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1), keyExtractor.apply(c2)); } // 1.8新增静态方法:执行键比较,采用内置比较方式,key的类必须实现Comparable public static <T, U extends Comparable<? super U>> Comparator<T> comparing( Function<? super T, ? extends U> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); } // 1.8新增静态方法:用于int类型键的比较 public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2)); } // 1.8新增静态方法:用于long类型键的比较 public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2)); } // 1.8新增静态方法:用于double类型键的比较 public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2)); } }
There are only two methods in the old version of Comparator, which are the first two methods. All subsequent default methods are new methods added in 1.8, using the new methods added in 1.8. Function: The interface can add default methods. Even with so many methods, the interface is still a functional interface, and compare is used to define the comparison method.
4. Comparison between the two
Comparable can be regarded as an internal comparator, and Comparator can be regarded as an external comparator.
A class can have orderliness by implementing the Comparable interface, or can add orderliness by specifying an additional Comparator.
The functions of the two are actually the same, so don’t mix them.
Let’s look at an example:
First define a model: User
public class User implements Serializable, Comparable<User> { private static final long serialVersionUID = 1L; private int age; private String name; public User (){} public User (int age, String name){ this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int compareTo(User o) { return this.age - o.age; } @Override public String toString() { return "[user={age=" + age + ",name=" + name + "}]"; } }
Then define a Comparator implementation class MyComparator
public class MyComparator implements Comparator<User> { @Override public int compare(User o1, User o2) { return o1.getName().charAt(0)-o2.getName().charAt(0); } }
Finally, the test class: Main
public class Main { public static void main(String[] args) { User u1 = new User(12, "xiaohua"); User u2 = new User(10, "abc"); User u3 = new User(15,"ccc"); User[] users = {u1,u2,u3}; System.out.print("数组排序前:"); printArray(users); System.out.println(); Arrays.sort(users); System.out.print("数组排序1后:"); printArray(users); System.out.println(); Arrays.sort(users, new MyComparator()); System.out.print("数组排序2后:"); printArray(users); System.out.println(); Arrays.sort(users, Comparator.reverseOrder());// 针对内置的排序进行倒置 System.out.print("数组排序3后:"); printArray(users); } public static void printArray (User[] users) { for (User user:users) { System.out.print(user.toString()); } } }
The running result is:
数组排序前:[user={age=12,name=xiaohua}][user={age=10,name=abc}][user={age=15,name=ccc}] 数组排序1后:[user={age=10,name=abc}][user={age=12,name=xiaohua}][user={age=15,name=ccc}] 数组排序2后:[user={age=10,name=abc}][user={age=15,name=ccc}][user={age=12,name=xiaohua}] 数组排序3后:[user={age=15,name=ccc}][user={age=12,name=xiaohua}][user={age=10,name=abc}]
Through the above example, we have a conclusion, that is, there are two ways to define the priority of sorting. Obviously, the Comparator comparator takes precedence over the internal sorting Comparable.
5. Summary
Comparable is sortable, and objects of classes that implement this interface automatically have the sortable function.
Comparator is a comparator. Implementing this interface can define a sorting method for a certain class.
When Comparator and Comparable exist at the same time, the former has higher priority.
The above is the detailed content of Comparative introduction to Comparable and Comparator in Java (code example). For more information, please follow other related articles on the PHP Chinese website!