Comparable和Comparator的排序之路

导读:本篇文章讲解 Comparable和Comparator的排序之路,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

如果说起比较,像我这样的小白第一时间想到的是1“等于”(==)1或者是1“不等于”(!=)2这种。那是因为正常情况下,java中的对象只能比较==和!=。但是在日常的开发中,我们会面临大量的数据,而此时有大批的“对象”等着我们给他们“排队”,此时就用到了“Comparable” 和“Comparator”接口。

下面我来简单介绍一下这两个接口:

1.Comparable接口简介

我们在开发中有时候需要对数据进行自然排序(像是数据从大到小,从a到z等等)时,这时就用到了Comparable接口。而他为什么叫自然排序呢,是因为他本身就带着一个compareTo(),而且此方法已经在底层源码中写好的,而我们只需要在自定义类中,重写compareTo()方法即可,他会自动比较调用方法的对象和参数的大小,结果自然而然就出来啦。

代码举例:

/**
* 商品类
*/
public class Goods implements Comparable{

    private String name;//商品名字
    private double price;//价格

    //指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序
    @Override
    public int compareTo(Object o) {
        //这里的o是object类型,转Goods是向下转型需要强转。强制转型可能会有错误,所以使用instanceof判断下
        if(o instanceof Goods){
            Goods goods = (Goods)o;
            if(this.price > goods.price){
                return 1;
            }else if(this.price < goods.price){
                return -1;
            }else{
//                return 0;
                return -this.name.compareTo(goods.name);//不加-是从低到高,加-是从高到低
            }
        throw new RuntimeException("传入的数据类型不一致!");
    }

    public Goods() {
    }

    public Goods(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

/*
 * 测试类
 */
public class CompareTest {
    @Test
    public void test(){
        Goods[] arr = new Goods[5];
        arr[0] = new Goods("lenovoMouse",34);
        arr[1] = new Goods("dellMouse",43);
        arr[2] = new Goods("xiaomiMouse",12);
        arr[3] = new Goods("huaweiMouse",65);
        arr[4] = new Goods("microsoftMouse",43);

        Arrays.sort(arr);

        System.out.println(Arrays.toString(arr));
    }
}

通过上方的代码,我们可以总结出重写comparaTo()的规则:

  • 如果当前对象this大于形参对象obj,则返回正整数
  • 如果当前对象this小于形参对象obj,则返回负整数
  • 如果当前对象this等于形参对象obj,则返回零

2.Comparator接口简介

当元素的类型实现类java.lang.Comparable接口无法满足于当前的需求,或者是既没有实现该接口又不想费劲改代码,此时就用到了我们的的专属定制——comparator接口,因此comparator接口的使用有被称为定制排序。也就是说,我们可以通过实现Comparator接口来创建一个新的比较器,然后通过该比较器对类或类的对象进行排序。

代码举例:

    @Test
    public void test1(){
        String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"};
        Arrays.sort(arr,new Comparator(){//创建一个接口实现类的对象,因此处只用1次,所以可以匿名

            //按照字符串从大到小的顺序排列
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof String && o2 instanceof  String){
                    String s1 = (String) o1;
                    String s2 = (String) o2;
                    return -s1.compareTo(s2);
                }
//                return 0;
                throw new RuntimeException("输入的数据类型不一致");
            }
        });
        System.out.println(Arrays.toString(arr));
    }

    @Test
    public void test2(){//此处用上面的自定义Goods类(商品类)
        Goods[] arr = new Goods[6];
        arr[0] = new Goods("lenovoMouse",34);
        arr[1] = new Goods("dellMouse",43);
        arr[2] = new Goods("xiaomiMouse",12);
        arr[3] = new Goods("huaweiMouse",65);
        arr[4] = new Goods("huaweiMouse",224);
        arr[5] = new Goods("microsoftMouse",43);

//把需要自定义排序的元素/属性赋值给创建继承comparator匿名内部类的匿名对象,重写其排序规则的方法
        Arrays.sort(arr, new Comparator() {
            //指明商品比较大小的方式:按照产品名称从低到高排序,再按照价格从高到低排序
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Goods && o2 instanceof Goods){
                    Goods g1 = (Goods)o1;
                    Goods g2 = (Goods)o2;
                    if(g1.getName().equals(g2.getName())){
                        return -Double.compare(g1.getPrice(),g2.getPrice());
                    }else{
                        return g1.getName().compareTo(g2.getName());
                    }
                }
                throw new RuntimeException("输入的数据类型不一致");
            }
        });

        System.out.println(Arrays.toString(arr));
    }

 

通过上方的代码,我们可以总结出重写compare()的规则:

重写compare(Object o1,Object o2)方法,比较o1和o2的大小:

  • 如果方法返回正整数,则表示o1大于o2
  • 如果返回0,表示相等
  • 返回负整数,表示o1小于o2

 

就此可以看出来Comparable接口与Comparator的使用上的区别:

Comparable接口的方式一旦指定,实现Comparable接口的对象都可以比较大小;而Comparator更像是一种临时工,用完(比较完)就走人。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/81359.html

(1)
小半的头像小半

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!