Comparable VS Comparator

一.概述

Java 中的排序是由 Comparable 和 Comparator 这两个接口来实现的。
Comparable表示可被排序的,实现该接口的类的对象自动拥有排序功能,属于内部顺序,但需要手动实现接口,侵入性比较强。
Comparator则表示一个比较器,一般情况, 这个比较器将作为一个参数进行传递。对待比较累的侵入性弱,但对算法代码实现侵入性强。

二.Comparable(自然排序)

源码如下:

public interface Comparable<T> {
    public int compareTo(T o);
 }
  • Comparable 的中文意思就是可被排序的,代表本身支持排序功能。只要我们的类实现了这个接口,那么这个类的对象就会自动拥有了可被排序的能力。而且这个排序被称为类的自然顺序。
  • 这个类的对象的列表可以被Collections.sort()和Arrays.sort()来执行排序。
  • 从源码中可以看到,该接口只有一个抽象方法compareTo() 这个方法主要就是为了定义我们的类所要排序的方式。compareTo()方法用于比较当前元素 a与指定元素 b的大小,结果为int值,如果a >b,int值>0; 如果a=b, int值=0;如果a<b, int值<0。

三.Comparator(定制排序)

在实际开发中,遇到当元素的类型实现了 Comparable 接口,但是它的排序方式不适合当前的操作;或者根本没有实现 Comparable接口,而又不方便修改代码。那么可以考虑使用定制一个 Comparator 的对象进行排序。

public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
}

Comparator 中文译为比较器,它可以作为一个参数传递到Collections. sort()和Arrays.sort()方法,来指定某个类的对象的列表的排序方式。

四.二者比较

  • Comparable 可以看做是内部比较器,Comparator 可以看做是外部比较器。
    一个类, 可以通过实现 Comparable 接口来自带有序性,也可以通过额外指定
  • Comparator 来附加有序性。二者的作用其实是一致的, 所以不要混用。

五.总结

  • Comparable为可排序的,实现该接口的类的对象自动拥有可排序功能。
  • Comparator为比较器,实现该接口可以定义一个针对某个类的排序方式。
  • Comparator与Comparable同时存在的情况下,前者优先级高。
  • Comparable和Comparator接口是用来对自定义的类class进行大小比较的。
  • Comparator和 Comparable的区别:Comparator定义在类的外部,而Comparable定义在类的内部。

六.具体实现

1.Comparable 定义在类的内部,需要覆写compareTo方法

用户自定义类型想要按照大小进行比较时,在定义类时,需要实现Comparable 接口 ,然后在类中重写compareTo方法比较规则由程序员自己定,例如,下列程序,按照User的年龄升序比较 不然会抛异常:
java.lang.ClassCastException: comparable.User cannot be cast to java.lang.Comparable
*/


public class Test01 {
    public static void main(String[] args) {
        TreeSet<User> treeSet = new TreeSet<>();

        User user1 = new User(20);
        User user2 = new User(10);
        User user3 = new User(35);
        User user4 = new User(29);
        User user5 = new User(25);

        treeSet.add(user1);
        treeSet.add(user2);
        treeSet.add(user3);
        treeSet.add(user4);
        treeSet.add(user5);

       for (User user:treeSet) {
           System.out.println(user);
       }
    }
}

//User类实现了Comparable接口,则只需要在类内部覆写compareTo方法,即可进行对象的比较
class User implements Comparable<User>{
    private int age;
    private String name;

    public User() {

    }
    public User(int age) {
        this.age = age;
    }
    public User(int age,String name) {
        this.age = age;
        this.name = name;
    }


 /*   @Override
    //倘若有多个属性的比较规则,按照如下方式写排序规则
    public int compareTo(User o) {
        if (this.age == o.age) {
            //String类型内部已经重写了compareTo方法,比较的时候直接调用方法即可
            //当年龄相等的时候比较name
            return this.name.compareTo(o.name);
        }else {
            //年龄不想等就按照年龄比较
            return  this.age - o.age;
        }
    }*/

    @Override
    public int compareTo(User o) {
        return  this.age - o.age;//升序
        // return  o.age - this.age;//降序
    }

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

2.Comparator 定义在类的外部

比较器Comparator
TreeMap的key或者TreeSet集合中的自定义类型的元素想要排序有两种实现方式:
1.实现java.lang.Comparable接口
2.Comparator比较器 有两种方式
方式一:单独写一个比较器,传入集合
方式二:创建集合的时候编写一个Comparator匿名内部类传入集合


public class Test02 {
    public static void main(String[] args) {
        WuGui wuGui1 = new WuGui(1000);
        WuGui wuGui2 = new WuGui(500);
        WuGui wuGui3 = new WuGui(800);
        //创建TreeSet集合的时候,需要使用这个比较器
        //TreeSet<WuGui> wuGuis = new TreeSet<>(); 这样不行,因为没有通过通过构造方法,传递比较器进去

        System.out.println("===============方式1比较器=================");
                                        //方式1:单独写一个比较器,传入集合
        TreeSet<WuGui> wuGuis0 = new TreeSet<>(new WuGuiComparator());
        wuGuis0.add(new WuGui(1800));
        wuGuis0.add(new WuGui(8200));
        wuGuis0.add(new WuGui(8100));
        for (WuGui wuGui99: wuGuis0) {
            System.out.println(wuGui99);
        }

        System.out.println("===============方式2比较器=================");
                                            //方式2:匿名内部类,传入集合
        TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() {
            @Override
            public int compare(WuGui o1, WuGui o2) {
                return o1.getAge() - o2.getAge();
            }
        });
        wuGuis.add(wuGui1);
        wuGuis.add(wuGui2);
        wuGuis.add(wuGui3);

        for (WuGui wuGui : wuGuis) {
            System.out.println(wuGui);
        }
    }
}

class WuGui {
    private int age;

    public int getAge() {
        return age;
    }

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

    public WuGui(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "小乌龟{" +
                "age=" + age +
                '}';
    }
}

//在WuGui的类外单独编写一个比较器
class WuGuiComparator implements Comparator<WuGui> {
    @Override
    public int compare(WuGui o1, WuGui o2) {
        //指定比较规则
        //按照年龄排序
        return o1.getAge() - o2.getAge();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值