java中的对比相关的几个接口长的还都挺像,搞不好就容易搞忘了是哪个了。所以抽出时间来看看他的源码,梳理梳理这2个接口,一方面是个总结,同时也方便记忆。 Comparable,顾名思义就是说能不能比,你去实现他就能比了,就Comparable了。 Comparator,顾名思义比较器,拿来比较的
1. Comparable接口定义
java.lang.Comparable<T>
此接口只有一个方法就是public int compareTo(T o); 比较方法。compareTo方法返回int型的负数、0、正数,分别代表小于、等于、大于指定的对象。对于想要进行比较/排序的类,可以实现Comparable接口,实现Comparable接口一定要重写compareTo方法。例如:
public class User implements Comparable<User>{
private String name;
private Integer age;
// 省略 get set 方法 和构造方法
@Override
public int compareTo(User o) {
return this.age.compareTo(o.age);
}
public static void main(String[] args) {
User u1 = new User("李白", 20);
User u2 = new User("杜甫", 40);
System.out.println(u1.compareTo(u2)); // 输出 -1
}
}
如上所见,使用和理解都很简单。
2. Comparator接口定义
public interface Comparator<T>
此接口定义了很多方法:
20180823153455315.png先看第一个:int compare(T o1, T o2); ,实现上面的compareTo相同的功能,如下:
import java.util.Comparator;
public class User implements Comparator<User>{
private String name;
private Integer age;
// 省略 get set 方法 和构造方法
@Override
public int compare(User o1, User o2) {
return (o1.getAge() < o2.getAge()) ? -1 : ((o1.getAge() > o2.getAge()) ? 1 : 0);
}
public static void main(String[] args) {
User u1 = new User("李白", 20);
User u2 = new User("杜甫", 40);
System.out.println(u1.compare(u1, u2)); // 输出 -1
}
}
对比上面的个compareTo方法后可以看出来,2个方法本质上并无太大差别。实际上他们的区别就是compareTo方法的实现是jdk已经实现过的,而compare则需要自己手动实现。
举个栗子: 我们的User类同时实现Comparator<user style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); box-sizing: border-box; margin: 0px; padding: 0px;">,Comparable <user style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); box-sizing: border-box; margin: 0px; padding: 0px;">两个接口后,我们的compareTo方法就可以写成这样:</user></user>
public class User implements Comparator<User>, Serializable,Comparable<User> {
private String name;
private Integer age;
// 省略 get set 方法 和构造方法
@Override
public int compare(User o1, User o2) {
return (o1.getAge() < o2.getAge()) ? -1 : ((o1.getAge() > o2.getAge()) ? 1 : 0);
}
@Override
public int compareTo(User o) {
return this.compare(this, o);
}
public static void main(String[] args) {
User u1 = new User("李白", 20);
User u2 = new User("杜甫", 40);
System.out.println(u1.compareTo(u2)); // 输出 -1
}
}
或者:
public class User implements Comparator<User>, Serializable,Comparable<User> {
private String name;
private Integer age;
// 省略 get set 方法 和构造方法
@Override
public int compare(User o1, User o2) {
return (o1.getAge() < o2.getAge()) ? -1 : ((o1.getAge() > o2.getAge()) ? 1 : 0);
}
@Override
public int compare(User o1, User o2) {
return o1.compareTo(o2);
}
@Override
public int compareTo(User o) {
return this.age.compareTo(o.age);
}
public static void main(String[] args) {
User u1 = new User("李白", 20, true);
User u2 = new User("杜甫", 40, true);
System.out.println(u1.compare(u1,u2)); // 输出 -1
}
}
2种实现方式可以相互调用,不过总要有一个方法去写实现,如果2个方法相互调用且都不写实现的话,那就呵呵了,最终就是相互调用到死,StackOverflow了。
然后是第二个方法:
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
这个方法有点意思,方法上的注释是:Returns a comparator that imposes the reverse ordering of this comparator.
意思就是把刚刚实现的排序倒过来一下。实现如下:
// User类与上面的User一样,实现了Comparator接口
public static void main(String[] args) {
User u1 = new User("李白", 20, true);
User u2 = new User("杜甫", 40, true);
System.out.println(u1.compare(u1,u2)); // 输出 -1
Comparator<User> reversed = u1.reversed();
System.out.println(reversed.compare(u1, u2)); // 输出 1
}
这个方法有点意思是有点意思,不过看他的定义就知道:default 方法,说明此方法是java8后面加的,所以要注意java的环境。
然后是第三个方法:
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);
};
}
看方法字面意思就知道,比一次后再比一次,就拿刚刚的方法来验证:
public static void main(String[] args) {
User u1 = new User("李白", 20, true);
User u2 = new User("杜甫", 40, true);
System.out.println(u1.compare(u1,u2)); // 输出 -1
Comparator<User> reversed = u1.reversed();
System.out.println(reversed.compare(u1, u2)); // 输出 1
// 定义一个对比之后再对比的Comparator,此处就用上面的倒序的那个Comparator
Comparator<User> thenComparing = u1.thenComparing(u1.reversed());
// 所以两次倒序后,负负得正,又是输出-1
System.out.println(thenComparing.compare(u1, u2)); // 输出 -1
}
后面的几个thenComparingInt
、 thenComparingLong
与这个差不多。
再下面的几个都是static方法:
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
看方法的实现,与上面的default方法reversed() 一模一样。
tuiguang.png推荐一下我的公众号: 【geekjc】,一起学习交流编程知识,分享经验,各种有趣的事,更多精彩内容,扫码进入小程序。
网友评论