Comparator接口与Comparable接口区别

一、 概述

在日常的开发工作中经常会遇到对自定义对象进行比较然后进行排序的场景,对自定义对象进行排序通常有两种实现方式:使用Comparable接口和Comparator接口。两种方式各有优劣,下面结合例子对两种实现方式做一个简单的分析。

二、Comparable接口

Comparable接口位于java.lang.Comparable,对象实现此接口并重写compareTo方法可以实现自定义的排序,这种方式使得类本身具有排序能力。Jdk文档中指出可以使用 Collection.sort()Arrays.sort() 对包含实现了此接口的类的List或者数组进行排序。
下面用一个对酒店进行排序的例子进行说明:

代码示例

public class Hotel implements Cloneable, Comparable<Hotel> {

    private int hotelId;

    private int star;

    private int score;

    private int comments;

    // 返回负数表示小于、正数表示大于、0表示相等, 星级越高排名越靠前,评分越高排名越靠前
    @Override
    public int compareTo(Hotel hotel) {
        if (this.star > hotel.star) {
            return -1;
        }  else if (this.star < hotel.star) {
            return 1;
        } else {
            return Integer.compare(hotel.score, this.score);
        }
    }

    public int getHotelId() {
        return hotelId;
    }

    public void setHotelId(int hotelId) {
        this.hotelId = hotelId;
    }

    public int getStar() {
        return star;
    }

    public void setStar(int star) {
        this.star = star;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public int getComments() {
        return comments;
    }

    public void setComments(int comments) {
        this.comments = comments;
    }


    public Hotel copy() {
        try {
            return (Hotel) this.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }

    @Override
    public String toString() {
        return "Hotel{" +
            "hotelId=" + hotelId +
            ", star=" + star +
            ", score=" + score +
            ", comments=" + comments +
            '}';
    }
}
public class ComparableTest {

    public static void main(String[] args) {
        List<Hotel> hotelList = new ArrayList<>();
        Hotel hotel = new Hotel();
        hotel.setHotelId(1);
        hotel.setStar(5);
        hotel.setScore(4);
        hotel.setComments(200);
        hotelList.add(hotel);

        Hotel hotel1 = hotel.copy();
        hotel1.setComments(500);
        hotel1.setScore(3);
        hotel1.setStar(4);
        hotel.setHotelId(2);
        hotelList.add(hotel1);

        Hotel hotel2 = hotel.copy();
        hotel2.setComments(1000);
        hotel2.setScore(2);
        hotel2.setStar(4);
        hotel2.setHotelId(3);
        hotelList.add(hotel2);

        System.out.println("排序前");
        for (Hotel item : hotelList) {
            System.out.println(item);
        }

        System.out.println("先按酒店星级进行排序然后按照评分排序");
        Collections.sort(hotelList);
        for (Hotel item : hotelList) {
            System.out.println(item);
        }

    }
}

输出结果:
在这里插入图片描述

三、Comparator接口

上面的实现方式很简单,但是如果当类对象本身没有实现Comparable接口(你不能要求所有的jar包提供方自定义的类都实现Comparable接口,这不合理也不科学),那该怎么来对这些对象进行排序呢?此时就该Comparator接口大显神威了。
下面仍以对酒店进行排序的代码进行说明:

代码示例

public class ComparatorTest {

    public static void main(String[] args) {
        List<Hotel> hotelList = new ArrayList<>();
        Hotel hotel = new Hotel();
        hotel.setHotelId(1);
        hotel.setStar(5);
        hotel.setScore(4);
        hotel.setComments(200);
        hotelList.add(hotel);

        Hotel hotel1 = hotel.copy();
        hotel1.setComments(500);
        hotel1.setScore(3);
        hotel1.setStar(4);
        hotel.setHotelId(2);
        hotelList.add(hotel1);

        Hotel hotel2 = hotel.copy();
        hotel2.setComments(1000);
        hotel2.setScore(2);
        hotel2.setStar(4);
        hotel2.setHotelId(3);
        hotelList.add(hotel2);

        System.out.println("排序前");
        for (Hotel item : hotelList) {
            System.out.println(item);
        }

        System.out.println("先按酒店星级进行排序然后按照评分排序");
        List<Hotel> sortHotelList = hotelList.stream().sorted(getComparator()).collect(Collectors.toList());
        for (Hotel item : sortHotelList) {
            System.out.println(item);
        }

    }

    private static Comparator<Hotel> getComparator() {
        return new Comparator<Hotel>() {
            @Override
            public int compare(Hotel o1, Hotel o2) {
                if (o1.getStar() > o2.getStar()) {
                    return -1;
                } else if (o1.getStar() < o2.getStar()) {
                    return 1;
                } else {
                    return Integer.compare(o2.getScore(), o1.getScore());
                }
            }
        };
    }

}

输出结果同上

使用Comparator.comparing().thenComparing实现

得益于JDK1.8新特性,还可以直接使用Comparator.comparing().thenComparing实现排序,不用再自定义比较器。

List<Hotel> sortHotelList = hotelList.stream().sorted(Comparator.comparing(Hotel::getStar)
            .thenComparing(Hotel::getScore).reversed()).collect(Collectors.toList());

四、区别

  • Comparable接口实现简单,需要重写CompareTo方法,可以使类本身具有排序能力
  • Comparator接口可以对不具有排序能力的类实现自定义排序,需要重写compare方法
  • Comparator.comparing().thenComparing 不用实现自定义比较器,简洁易用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值