Java如何让自定义类型具有可比较大小的能力

一、背景

  • Java中基本数据类型之间可以使用比较运算符>、<、>=、<=、==、!=等进行比较;
  • 引用数据类型之间进行比较时,使用继承于Object类的equals方法,对象之间使用==进行比较时,默认调用equals方法,实质上比较的是对象所在地址;所以如果使用equals方法进行比较,主要对其进行重写;
  • equals方法的缺点在于只能进行“相等”比较,无法比较大小关系;

二、两种方法

  • 方式一,自然排序:自定义类本身实现java.lang.Comparable接口,并重写其compareTo方法;
  • 方式二,定制排序:需要具体比较类实现java.util.Comparator接口,并重写其compare方法,使用前必须具有该比较类实例化对象;

方式一,自然排序:

  • 内置类,如字符串、集合类等默认实现java.lang.Comparable接口,且重写其compareTo方法,默认排序方式为升序
  • 自定义类若想具备比较大小的能力,需要实现java.lang.Comparable接口,且重写其compareTo方法;
  • 如果想改变排序方式为降序,则将此时compareTo方法的返回值取反即可。可理解为升序时将“大”的对象(返回值为正数)放在后面,在降序时则是想让其放在前面,此时想法让算法内部认为“大”的对象变“小”即可,所以将其返回值取反即可实现该功能;

此实现方式要求自定义类必须实现java.lang.Comparable接口,且重写其compareTo方法,一旦实现则该类永久具备比较大小的能力。
在这里插入图片描述

@Data
public class Book implements Comparable<Book>{
    private int price;
    private String bookName;
    private String author;

    public Book(){

    }

    public Book(int price, String bookName, String author) {
        this.price = price;
        this.bookName = bookName;
        this.author = author;
    }

    @Override
    public int compareTo(Book o) {
//        return this.price-o.price;  // 升序
        return o.price-this.price;  // 降序
    }
}
    // 自定义类实现Comparable接口,并重写其compareTo方法;
    // 按照Book类的price属性大小由高到低进行排序
    @Test
    public void comparableTest(){
        Book book1 = new Book(99, "《叶惠美》", "周杰伦");
        Book book2 = new Book(88, "《Jay》", "周杰伦");
        Book book3 = new Book(111, "《魔杰座》", "周杰伦");
        // System.out.println(book1.compareTo(book2));
        // System.out.println(book1.compareTo(book3));
        Book[] books=new Book[]{book1,book2,book3};
        System.out.println("排序前:"+Arrays.toString(books));
        Arrays.sort(books);
        System.out.println("排序后:"+Arrays.toString(books));

    }
排序前:[Book(price=99, bookName=《叶惠美》, author=周杰伦), Book(price=88, bookName=Jay, author=周杰伦), Book(price=111, bookName=《魔杰座》, author=周杰伦)]
排序后:[Book(price=111, bookName=《魔杰座》, author=周杰伦), Book(price=99, bookName=《叶惠美》, author=周杰伦), Book(price=88, bookName=Jay, author=周杰伦)]

方式二,定制排序:

  • 有些类可能存在以下这些情况,此时需要用到定制排序:1)类内部并未实现java.lang.Comparable接口,且对其内部代码又不方便进行修改;2)类虽然实现java.lang.Comparable接口,具备比较大小的能力,但是当前排序方式不满足显示需求,则需要对其排序方式进行修改;
  • 定制排序,需要实现一个具体比较类实现java.util.Comparator接口,并重写其compare方法,使用前必须具有该比较类实例化对象;

此实现方式要求自定义类进行比较之前,必须获取到一个对应该类的比较类对象,此时该自定义类临时具备特定方式的比较能力。
在这里插入图片描述

// Book对应比较器:实现Comparator接口,并重写其compare方法;
class BookComparator implements Comparator<Book>{
    @Override
    public int compare(Book o1, Book o2) {
        return o1.getPrice()-o2.getPrice();  // 升序
    }
}
@Test
    public void comparatorTest(){
        Book book1 = new Book(99, "《叶惠美》", "周杰伦");
        Book book2 = new Book(88, "《Jay》", "周杰伦");
        Book book3 = new Book(111, "《魔杰座》", "周杰伦");
        // 获取该类对应比较器对象
        BookComparator comparator = new BookComparator();
//        System.out.println(comparator.compare(book1,book2));
//        System.out.println(comparator.compare(book1,book3));
        Book[] books=new Book[]{book1,book2,book3};
        System.out.println("排序前:"+Arrays.toString(books));
        Arrays.sort(books,comparator);
        System.out.println("排序后:"+Arrays.toString(books));
    }
排序前:[Book(price=99, bookName=《叶惠美》, author=周杰伦), Book(price=88, bookName=Jay, author=周杰伦), Book(price=111, bookName=《魔杰座》, author=周杰伦)]
排序后:[Book(price=88, bookName=Jay, author=周杰伦), Book(price=99, bookName=《叶惠美》, author=周杰伦), Book(price=111, bookName=《魔杰座》, author=周杰伦)]

在平时使用时,我们很少单独创建一个比较器类,比如BookComparator,而是在类似Arrays.sort方法的参数中直接传入参数,使用匿名子类的方式,示例如下:

        Arrays.sort(books, new Comparator<Book>() {
            @Override
            public int compare(Book o1, Book o2) {
                return o1.getPrice()-o2.getPrice();
            }
        });

资料来源:尚硅谷

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NorthSmile

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值