关于Compareable和Comparator

1、Compareable使用


通常某个类具有内在的排序规则,如按时间 长度等维度是可排序的话,建议实现Compareable接口,重写compareTo方式

这样的话存放数组或集合框架中时,我们可用Arrays.sort(x)或Collections.sort(x)按其自然顺序排序。

例子

import java.util.Objects;

public class Model implements Comparable<Model>{
    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Model model = (Model) o;
        return age == model.age &&
                Objects.equals(name, model.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public int compareTo(Model o) {
        int result = name.compareTo(o.getName());
        if(result == 0){
            if(age<o.getAge()){
                return -1;
            }
            if(age>o.getAge()){
                return 1;
            }else{
                return 0;
            }
        }else{
            return result;
        }
        
    }
}
View Code

2、重写compareTo原则


对于TreeSet TreeMap有序集合,判断某个对象是否存在是按Compareable接口来判断的。

所以当我们重写equals hashCode compareTo方法时,需要用相同的域来判断,这3者强烈建议保持一致。

否则如何两个对象obj1和obj2 obj1.equals(obj2)==true;而obj1.compareTo(obj2) != 0

此时如何存入TreeSet中就会当做两个不同的对象,容易产生迷惑。

代码:

import java.util.Objects;

public class Model implements Comparable<Model>{
    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

    @Override
    public int hashCode() {
        return Objects.hash(age);
    }

    @Override
    public int compareTo(Model o) {
        int result = name.compareTo(o.getName());
        if(result == 0){
            if(age<o.getAge()){
                return -1;
            }
            if(age>o.getAge()){
                return 1;
            }else{
                return 0;
            }
        }else{
            return result;
        }

    }
}
View Code

此对象按age来判断是否相等,而compareTo是按name和age来判断是否相等

测试存入TreeSet

public static void main(String[] args) throws IOException {
        Model model1 = new Model();
        model1.setAge(12);
        model1.setName("xiaoming");

        Model model12 = new Model();
        model12.setAge(12);
        model12.setName("xiaoli");

        TreeSet<Model> treeSet = new TreeSet<Model>();
        treeSet.add(model1);
        treeSet.add(model12);
        System.out.println(treeSet.size());
    }
View Code

执行返回:2 

这样从语义上就很让人迷惑了!

3、与Comparator区别


Compareable是一个类必须实现此接口重写compareTo方法,在类的内部决定如何排序

而Comparator并不要求类一定要实现接口,它是一种额外的附件排序

上代码:

public static void main(String[] args) throws IOException {
        Model model1 = new Model();
        model1.setAge(13);
        model1.setName("xiaoming");

        Model model12 = new Model();
        model12.setAge(12);
        model12.setName("xiaoli");

        List<Model> modelList = new ArrayList<Model>();
        modelList.add(model1);
        modelList.add(model12);
        Collections.sort(modelList, (o1, o2) -> {
            if(o1.getAge() < o2.getAge()){
                return -1;
            }
            if(o1.getAge() > o2.getAge()){
                return 1;
            }else{
                return 0;
            }
        });

        modelList.forEach(model -> System.out.println(model));


    }
View Code

执行返回:

Model{name='xiaoli', age=12}
Model{name='xiaoming', age=13}

总结:

1、Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

2、前者固定,后者灵活。后者可实现数据和比较逻辑分离

大多数情况个人建议Comparator接口外挂实现。

猜你喜欢

转载自www.cnblogs.com/yangfei629/p/11392109.html