Comparable
package java.lang;
import java.util.*;
public interface Comparable<T>
{
public int compareTo(T o);
}
致定义了一个compareTo方法,比较此对象和参数对象o的大小,若此对象小则返回负数,若此对象大则返回正数,若相等则为0
实现了Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序。
使用场景:
Comparable相当于一个内部比较器,他是在定义这个类的时候implement的
如果我们自己写一个类A的时候,直接public class A implements Comparable<A>
那么new出的对象a便可以a.compareTo,支持排序
Comparator
package java.util;
public interface Comparator<T>
{
int compare(T o1, T o2);
boolean equals(Object obj);
}
Comparator实现了compare和equals方法
其中compare是必须实现的,equals方法可以选择不实现
compare(T o1, T o2) 是“比较o1和o2的大小”,若o1小则返回负数,若o1大则返回正数,若相等则为0
使用场景:
Comparator相当于一个外部比较器
当已经有了一个类A,而且这个类A因为没有在类内部实现Comparable接口而不支持排序,并且不能修改类A的源代码(或比较繁琐)时,使用Comparator接口实现一个类A的比较器
public class AComparator implements Comparator<A> {
public int compare(A a1, A a2) {
return a1.data - a2.data;
}
}
调用时new Acomparator()
来调用compare方法
注意泛型
以上都是如何去比较一个类两个实例的大小,那么在定义一个类的时候如何限定我传入的参数类型都是可以比较大小的,以便在类中可以调用compareTo方法比较参数类型下的实例,那就需要泛型
正如源代码中所看,compare comparator接口都泛型化
有时我们会在类中发现<T extends Comparable<? super T>>
这样的表达
首先 ?表示通配符,代表其中类型的一种(注意是一种),但不知道这个类型具体是什么,那么? 和 T的区别在哪里呢
重要:
1 T用在模板定义类时,将数据类型参数化,他不可以实例化对象
2 ?用在实例化对象时,不确定具体类型到底是什么,只是给出一个范围,是这个范围中的一种
区别就是一个用在定义类时,一个是类已经写好了要实例化对象时
就像上文所说,?实例化对象时需要给出一个范围,那么这个范围就由super extends实现
? extends xx
//表示上界类型通配符,我虽然不知道这个类型具体是什么,但他是xx和xx的子类
? super xx
//表示下界类型通配符,我虽然不知道这个类型具体是什么,但他是xx和xx的父类
当然两者还有区别,包括extends用于读取参数列表,super用于写入参数列表,在此不赘述,看泛型一章
T定义类时模板所用的T便只有extends一种限定符,表示上界
回到<T extends Comparable<? super T>>
1 类型T是某些类中的一种(是对定义T的限制 T extends)
2 这些类实现了Comparable接口(Comparable<T>
实现这个接口需要指定这个类型,而我不知道这个类型是什么故用通配符 ?)
3 我不知道这个实现比较接口的类型是什么,但他是T和T的父类
即 T的限制是: 自己或者父类实现Comparable接口
这种写法比较<T extends Comparable<T>>
T的限制是:自己实现Comparable接口
举例:子类 Apple 父类 Fruit 父类Fruit实现了Comparable接口
第二种写法 Apple不在T的范围内,若想传入Apple参数,Apple需要自己实现接口,并只能和自己同类型的Apple比较大小
第一种写法 Apple在T的范围内,可以传入
So
<T extends Comparable<? super T>>
这样的类型参数对所传入的参数限制更少,提高了 API 的灵活性,在保证类型安全的前提下,要使用限制最少的类型参数。推荐。