Comparable和Comparator的 区别

一、概述:

对一组数据进行排序(升序或降序),在Java中有很多方式,可以自己手写排序算法(冒泡、快速、二叉树排序等),但一般都采用JDK为我们提供的现有的2个接口,Comparable和Comparator。

二、相同点:

  1. 两者都是用来用作对象之间的比较,都可以自定义比较规则。
  2. 两者都是返回一个描述对象之间关系的int。

三、区别:

  1. Comparable是java.lang包下的,Comparator是java.util包的。
  2. 实现Comparable接口必须重写compareTo(T o)方法,实现Comparator接口必须重写compare(T o1,T o2)方法。.
  3. Comparable是内在比较器,实现这个接口的类的对象可以直接比较:this.compareTo(this),这个类也支持排序,由该类对象组成的集合可以直接使用Collections.sort方法排序,此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。Comparator是外在比较器,如果想比较两个类又没有实现Comparable或者想实现自定义排序的,可以用Comparator。
  4. Comparator与Comparable同时存在的情况下,比较器Comparator优先级高。
  5. 使用Comparable需要修改原先的实体类,是属于一种自然排序,而Comparator 是不用修改原先的类的实现一个新的比较器 。Comparator实际应用广。

四、例子:

通俗来说,如果一个实体类实现了Comparable接口来实现排序规则,使用一段时间后,如果想去改变这个排序规则,基于“开闭原则”对修改关闭对扩展开放,我们可以通过Comparator接口来实现新的排序规则让实体类去采纳,使用一段时间后,如果还想改变,再通过Comparator接口实现一个新的排序规则即可。不影响类的封装性,易于扩展。

实体类Book实现了Comparable接口,比较规则是按书价大小。将多个Book对象存储在Set容器中,存储顺序是按照compareTo的规则。

package com.orange.sort;

public class Book implements Comparable{

    private String bookName;
    private int bookPrice;

    public Book() {
    }

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

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public int getBookPrice() {
        return bookPrice;
    }

    public void setBookPrice(int bookPrice) {
        this.bookPrice = bookPrice;
    }

    @Override
    public String toString() {
        return "Book{" +
                "bookName='" + bookName + '\'' +
                ", bookPrice='" + bookPrice + '\'' +
                '}';
    }

    @Override
    public int compareTo(Book o) {
        int minusPrice=this.getBookPrice()-o.getBookPrice();
        return minusPrice;
    }
}

测试:

    @Test
    public void test(){

        TreeSet set = new TreeSet<>();


        Book book1 = new Book("A", 1);
        Book book2 = new Book("B", 5);
        Book book3 = new Book("C", 3);
        Book book4 = new Book("D", 4);

        set.add(book1);
        set.add(book2);
        set.add(book3);
        set.add(book4);
        for(Book book:set){
            System.out.println(book);
        }
    }

结果:按照书价排序

Book{bookName='A', bookPrice='1'}
Book{bookName='C', bookPrice='3'}
Book{bookName='D', bookPrice='4'}
Book{bookName='B', bookPrice='5'}

针对上述例子,此时如果想改变排序规则,在不破坏原实体类的封装性的前提下,可实现Comparator接口制定新规则,在创建TreeSet时,传入Comparator:

  public void test2(){
        TreeSet set = new TreeSet<>(new Comparator() {
            @Override
            public int compare(Book o1, Book o2) {
                return o1.getBookName().compareTo(o2.getBookName());
            }
        });
        Book book1 = new Book("A", 1);
        Book book2 = new Book("B", 5);
        Book book3 = new Book("C", 3);
        Book book4 = new Book("D", 4);

        set.add(book1);
        set.add(book2);
        set.add(book3);
        set.add(book4);

        for(Book book:set){
            System.out.println(book);
        }
    }

结果:按照书名排序

Book{bookName='A', bookPrice='1'}
Book{bookName='B', bookPrice='5'}
Book{bookName='C', bookPrice='3'}
Book{bookName='D', bookPrice='4'}

你可能感兴趣的:(JavaSe,java,算法)