java里Comparable和Comparator的相同和不同

一:Comparable

排序接口,相当于实现了该类接口就可赋予类一个排序属性。

java里Comparable和Comparator的相同和不同 可以看出,该接口的类型为泛型,也就是说T的位置既可以有自定义类型,又可以有原有的类型。

java里Comparable和Comparator的相同和不同

里面只有一个函数,因此继承该接口的类都必须重写这个函数compareTo()

示例:学生类,先根据年龄排序,再根据name排序。

package day_10;


public class student implements Comparable<student> {
    int age;
    String name;
    student(int age,String name){
        this.age=age;
        this.name=name;
    }
    //compareTo函数重写
    @Override
    public int compareTo(student s){
        int num=this.age-s.age;  //这是降序,升序的话就改成s.age-this.age
        return num==0?this.name.compareTo(s.name):num;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        student student = (student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        int result = age;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }

    @Override
    public String toString(){
        return "student{age="+age+",name='"+name+"'};";
    }

   
}

 

二:Comparator

比较器接口,相当于实现了该接口之后就能实现一个比较器。比较器是实实在在存在的,可以类似于参数一样进行传递。

package day_10;
//必须导包
import java.util.Comparator;
//下面就是一个自定义的排序类
public class comparator implements Comparator<student> {
    @Override
    public  int compare(student s1, student s2){
        int num=s1.age-s2.age;
        return num==0?s1.name.compareTo(s2.name):num;
    }
}


//在主类中调用
        TreeSet<student> treeSet = new TreeSet<student>(new comparator());//匿名对象
或 
        comparator c1=new comparator();
        TreeSet<student> treeSet = new TreeSet<student>(c1);

写成匿名类的形式: 

 TreeSet<student> treeSet = new TreeSet<student>(new Comparator<student>() {
            @Override
            public int compare(student s1, student s2) {
                int num = s1.age - s2.age;
                return num == 0 ? s1.name.compareTo(s2.name) : num;
            }
        });

 

   这个一看就能发现这个可以省去好多重复操作,比如有多个类排序操作一样,就没必要在每个类中都实现一次Comparable接口,只需要写一个比较器,然后像传参数一样传递其即可。

例二: 

        ArrayList<student>arrayList=new ArrayList<student>();
        arrayList.add(stu1);
        Collections.sort(arrayList,c1);

 

三:优劣相比 

           一些场景下二者可以混合使用。并且二者都是接口。

           用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是使用Comparable的话还得破开类的代码,这就违反了开闭原则。

           用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑(因为这个接口里有很多函数功能),使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

 

上一篇:PriorityQueue详解


下一篇:Comparator接口