Comparable接口和Comparator接口的使用和区别
转载于:https://blog.csdn.net/IT_10/article/details/104747173
Comparable
Comparable接口在JDK8中的源码:
package java.lang;
import java.util.*;
package java.lang;
public interface Comparable<T> {
public int compareTo(T o);
}
用法:
public class User implements Comparable<User>{
private Integer id;
private Integer age;
public User() {
}
public User(Integer id, Integer age) {
this.id = id;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
'}';
}
public int compareTo(User o) {
if(this.age > o.getAge()) {
return 1;
}else if(this.age < o.getAge()) {
return -1;
}else{
return 0;
}
}
}
public class Test {
public static void main(String[] args) {
User user1 = new User(1, 14);
User user2 = new User(2, 12);
User user3 = new User(3, 10);
User[] users = {user1, user2, user3};
Arrays.sort(users);
Arrays.stream(users).forEach(System.out::println);
}
}
int compareTo(T o)
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
参数: o - 要比较的对象。
返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
抛出:ClassCastException - 如果指定对象的类型不允许它与此对象进行比较
Comparator
Comparator接口在JDK8中的源码:
package java.util;
import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;
public interface Comparator<T> {
int compare(T o1, T o2);
//还有很多其他方法...
}
使用:
public class Child {
private Integer id;
private Integer age;
public Child() {
}
public Child(Integer id, Integer age) {
this.id = id;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Child{" +
"id=" + id +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Child child1 = new Child(1, 14);
Child child2 = new Child(2, 12);
Child child3 = new Child(3, 10);
List<Child> list = new ArrayList<>();
list.add(child1);
list.add(child2);
list.add(child3);
Collections.sort(list, new Comparator<Child>() {
@Override
public int compare(Child o1, Child o2) {
return o1.getAge() > o2.getAge() ? 1 : (o1.getAge() == o2.getAge() ? 0 : -1);
}
});
// 或者使用JDK8中的Lambda表达式
//Collections.sort(list, (o1, o2) -> (o1.getAge()-o2.getAge()));
list.stream().forEach(System.out::println);
}
}
或者也可以通过实现的方式使用Comparator接口:
import java.util.Comparator;
public class Child implements Comparator<Child> {
private Integer id;
private Integer age;
public Child() {
}
public Child(Integer id, Integer age) {
this.id = id;
this.age = age;
}
@Override
public int compare(Child o1, Child o2) {
return o1.getAge() > o2.getAge() ? 1 : (o1.getAge() == o2.getAge() ? 0 : -1);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Child{" +
"id=" + id +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Child child1 = new Child(1, 14);
Child child2 = new Child(2, 12);
Child child3 = new Child(3, 10);
List<Child> list = new ArrayList<>();
list.add(child1);
list.add(child2);
list.add(child3);
Collections.sort(list, new Child());
list.stream().forEach(System.out::println);
}
}
Comparator接口其他默认方法的用法
reversed方法
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
这个方法是用来生成一个逆序器,比如我们开始需要得到一个正序的排序序列,然后又想得到一个反转的排序序列,就可以使用该方法。比如:
public class Test {
public static void main(String[] args) {
Child child1 = new Child(1, 14);
Child child2 = new Child(2, 12);
Child child3 = new Child(5, 10);
Child child4 = new Child(4, 10);
List<Child> list = new ArrayList<>();
list.add(child1);
list.add(child2);
list.add(child3);
list.add(child4);
Comparator<Child> comparator = Comparator.comparingInt(x -> x.getAge());
Collections.sort(list, comparator);
list.stream().forEach(System.out::println);
Collections.sort(list, comparator.reversed());
list.stream().forEach(System.out::println);
}
}
thenComparing
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
该方法是在原有的比较器上再加入一个比较器,比如先按照年龄排序,年龄相同的在按照id排序。比如:
public class Test {
public static void main(String[] args) {
Child child1 = new Child(1, 14);
Child child2 = new Child(2, 12);
Child child3 = new Child(5, 10);
Child child4 = new Child(4, 10);
List<Child> list = new ArrayList<>();
list.add(child1);
list.add(child2);
list.add(child3);
list.add(child4);
Comparator<Child> comparator = Comparator.comparingInt(x -> x.getAge());
Collections.sort(list, comparator);
list.stream().forEach(System.out::println);
System.out.println("-----");
Collections.sort(list, comparator.thenComparing(x->x.getId()));
list.stream().forEach(System.out::println);
}
}
Comparable接口和Comparator接口的区别
- Comparable接口位于java.lang包下;Comparator位于java.util包下
- Comparable接口只提供了一个compareTo()方法;Comparator接口不仅提供了compara()方法,还提供了其他默认方法,如reversed()、thenComparing(),使我们可以按照更多的方式进行排序
- 如果要用Comparable接口,则必须实现这个接口,并重写comparaTo()方法;但是Comparator接口可以在类外部使用,通过将该接口的一个匿名类对象当做参数传递给Collections.sort()方法或者Arrays.sort()方法实现排序。Comparator体现了一种策略模式,即可以不用要把比较方法嵌入到类中,而是可以单独在类外部使用,这样我们就可有不用改变类本身的代码而实现对类对象进行排序。