1、Java提供了Comparable接口,其主要作用是用来排序,这个接口中定义了一个 compareTo(Obj obj) 方法,该方法返回了一个整数值,实现该接口的类必须实现重写该方法,然后实现了该接口类的对象就可以比较比大小了。
2、当一个对象调用该方法进行比较时,比如obj1.comparaTo(obj2),如果返回值是0则相等,返回值是正整数则obj1更大,返回值是负整数则obj2更大。
3、其中这些类实现了Comparable接口:BigDecimal,Character,Boolean,String,Data,Time等类。
4、那么接下来我们就用TreeSet类举个例子,我们知道TreeSet与HashSet使用hash算法决定储存位置不同,是采用红黑树的数据结构来储存结合元素,并且TreeSet类支持两种排序方法:自然排序和定制排序,其中自然排序就可以用来实现Comparable接口。
class T implements Comparable{//我们用T类实现Comparable接口
int count;//定义一个实例变量
public T(int count){//包含一个参数的构造器
this.count = count;}
@Override//重写toString方法
public String toString(){
return "SetMap.T[count:" + count + "]";}
@Override//重写equal方法
public boolean equals(Object obj){
if (this == obj){return true;}
if (obj != null && obj.getClass() == T.class){
T t = (T) obj;
return t.count == this.count;}
return false;
}
@Override//重写compareTo比较方法
public int compareTo(Object obj) {
T t = (T)obj;
return count > t.count ? 1: count < t.count ? -1 : 0;//等同Integer.compare(count, t.count);}}
public class TreeSetTest {
public static void main(String[] args){
TreeSet ts = new TreeSet();//自然排序
T t1 = new T(5);//添加元素
ts.add(t1);
T t2 = new T(-3);
ts.add(t2);
T t3 = new T(9);
ts.add(t3);
T t4 = new T(-2);
ts.add(t4);
System.out.println(ts);//输出集合}}
可以看到输出的集合是按我们重写的方法进行顺序排列的,这里多说一句对于TreeSet甚至HashSet尽量不要修改,会导致位置和实际元素不一致。
再举个例子,我们在二分搜索树或者堆这些数据结构中都会实现这个类,同时会用到泛型的知识。
public class BinarySearchTree<T extends Comparable<T>> {
...//定义变量、构造器、其他函数
public void insert(T e){//这里举出插入的具体使用方法,因为就是比较数值大小这里不重写方法
root = insert(root,e);
}
public BinaryTreeNode<T> insert(BinaryTreeNode<T> node,T e){
if (node ==null){//递归基,当递归到某节点的左或右空子树时,新建一个节点插入进来
size++;
return new BinaryTreeNode<T>(e);
}
if (e.compareTo(node.data)<0){//插入元素与当前节点比较小,则进入左子树
node.lc = insert(node.lc,e);
}
else if (e.compareTo(node.data)>0){//插入元素与当前节点比较大,则进入右子树
node.rc = insert(node.rc,e);
}
else {//出错
System.out.println("insert error! ");
}
return node;//返回到升一级
}
}
1、Java提供了Compartor接口,其主要作用也是用来排序,这个接口中定义了一个 int compare(T obj1, T obj2) 方法,该方法返回了一个整数值,实现该接口的类必须实现重写该方法,然后实现了该接口类的对象就可以比较比大小了。
2、当调用该方法时进行比较时,如果返回值是0则相等,返回值是正整数则obj1更大,返回值是负整数则obj2更大。
3、Comparator接口是函数式接口,因此建议使用Lambda表达式替代重写方法。
4、那么接下来我们就依旧用TreeSet类举个例子,定制排序就可以用来实现Comparator接口。
class T{//我们创建一个T外部类
int count;//定义一个实例变量
public T(int count){//包含一个参数的构造器
this.count = count;}
@Override//重写toString方法
public String toString(){
return "SetMap.T[count:" + count + "]";}
@Override//重写equal方法
public boolean equals(Object obj){
if (this == obj){return true;}
if (obj != null && obj.getClass() == T.class){
T t = (T) obj;
return t.count == this.count;}
return false;
}
public class TreeSetTest {
public static void main(String[] args){
TreeSet ts1 = new TreeSet((o1,o2) ->{//定制排序使用lambda表达式实现comparator
T t5 = (T)o1;//需要强制转换类型
T t6 = (T)o2;
return t5.count > t6.count ? -1 : t5.count < t6.count ? 1 : 0; });//同Integer.compare(t5.count, t6.count)
T t11 = new T(5);//添加元素
ts1.add(t11);
T t21 = new T(-3);
ts1.add(t21);
T t31 = new T(9);
ts1.add(t31);
T t41 = new T(-2);
ts1.add(t41);
System.out.println(ts1);
可以看到输出的集合是按我们Lambda方法进行顺序排列的.
Comparable接口,需实现接口和看情况重写方法来使用。而Comparator接口无需实现接口,可以直接Lambda实现函数式接口或者重写。简单情况来说如果是实现一类中大量比较操作建议实现Comparable接口,而只是临时用一下甚至只用一次或是定制规则,建议用Comparator.