Comparable 和 Comparator 的区别和使用

在我们实际开发过程中,经常会遇到各种各样的排序,我们都知道,基本数据类型排序就是按照数值大小排序。

如果我们需要按照对象的某一个属性进行对象的比较排序,比如,按照商品的价格对商品进行排序,或者按照学生的升高对学生进行排序,这就涉及到对象间的排序。
应该怎么做呢?

一、自然排序:java.lang.Comparable

java.lang包下的Comparable接口会强行对他的实现类进行排序,这种排序规则称之为类的自然排序。例如String类,以及基本数据类型的包装类如IntegerDouble等都实现了Comparable接口并重写了**compareTo()**方法。默认都是有小到大排序。

如果我们需要对自定义对象进行排序,则需要实现Comparable 接口 并重写compareTo()方法,对象间通过conpareTo的返回值进行大小比较,如果大于当前对象则返回整数一般为 1 ,如果小于当前对象 则返回负数,一般为 -1,如果相等则 返回 0

另外实现了,Comparable 接口的对象都可以使用Arrays.sort(),以及Collections.sort()方法进行排序。

import java.util.Arrays;

class test {
    public static void main(String[] args) {
        Product products [] = new Product[4];
        Product product = new Product("A",12d);
        products[0] = product;
        Product product1 = new Product("B",10d);
        products[1] = product1;
        Product product2 = new Product("C",18d);
        products[2] = product2;
        Product product3 = new Product("D",1d);
        products[3] = product3;
        int i = product.compareTo(product1);
        System.out.println("比较结果:"+i);
        System.out.println("排序前:"+Arrays.toString(products));
        Arrays.sort(products);
        System.out.println("排序后:"+Arrays.toString(products));

    }
}


public class Product implements Comparable<Product>{
    private String productName;

    private Double price;

    public Product(String productName, Double price) {
        this.productName = productName;
        this.price = price;
    }
    public Product() {
    }
    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public Double getPrice() {
        return price;
    }

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

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

    @Override
    public int compareTo(Product o) {
        if(this.price>o.price){
            return 1;
        }else if(this.price<o.price){
            return -1;
        }else{
            return 0;
        }
    }
}

上面我们在compareTo方法里对price进行排序。当前对象price大于传入对象price则为1,小于则为-1,等于则为0; 可以看到使用 Arrays.sort(products);进行对象排序也是可以的。

比较结果:1
排序前:[Product{productName='A', price=12.0}, Product{productName='B', price=10.0}, Product{productName='C', price=18.0}, Product{productName='D', price=1.0}]
排序后:[Product{productName='D', price=1.0}, Product{productName='B', price=10.0}, Product{productName='A', price=12.0}, Product{productName='C', price=18.0}]

二、定制排序:java.util.Comparator

如果当前对象并没有实现Comparable接口,我们又不想对原有代码进行改动,可以考虑使用Comparator强行对多个对象进行整体排序。

相当于构建了一个比较器,对多个对象进行比较排序。我们无需对原有代码进行改动,只需要对相应的对象,专门构建一个Comprator比较器,在进行数据排序的时候,只需要将比较器传递Arrays.sort()或者Collections.sort()方法即可。

排序规则也可以定制化,可以创建一个价格比较器,也可以创建一个重量比较器等。

import java.util.Arrays;
import java.util.Comparator;

class Test{
    public static void main(String[] args) {
        Student students[] = new Student[4];
        students[0] = new Student("张三",22,165.8d);
        students[1] = new Student("李四",28,176.8d);
        students[2] = new Student("王五",19,188.8d);
        students[3] = new Student("赵六",20,166.8d);
        Arrays.sort(students,new AgeComparator());
        System.out.println("按年龄排序:"+Arrays.toString(students));

        Arrays.sort(students,new HeightComparator());
        System.out.println("按身高排序:"+Arrays.toString(students));


    }
}


class AgeComparator implements Comparator<Student>{
    /**
     * 定制年龄比较器
     */
    @Override
    public int compare(Student o1, Student o2) {
        if(o1.getAge()>o2.getAge()){
            return 1;
        }else if(o1.getAge()<o2.getAge()){
            return -1;
        }else{
            return 0;
        }
    }
}


class HeightComparator implements Comparator<Student>{
    /**
     * 定制身高比较器
     */
    @Override
    public int compare(Student o1, Student o2) {
        if(o1.getHeight()>o2.getHeight()){
            return 1;
        }else if(o1.getHeight()<o2.getHeight()){
            return -1;
        }else{
            return 0;
        }
    }
}



public class Student {
    private String name;
    private int age;
    private double height;

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public Student() {

    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }
}

Student 有age和height两个属性都可以排序,我们分别定制一个年龄排序AgeComparator ,和身高排序HeightComparator

按年龄排序:[Student{name='王五', age=19, height=188.8}, Student{name='赵六', age=20, height=166.8}, Student{name='张三', age=22, height=165.8}, Student{name='李四', age=28, height=176.8}]
按身高排序:[Student{name='张三', age=22, height=165.8}, Student{name='赵六', age=20, height=166.8}, Student{name='李四', age=28, height=176.8}, Student{name='王五', age=19, height=188.8}]

我么将不同的Comparator 交给 Arrays.sort()将会得到不同的排序结果。扩展性很强,侵入性小。

总结

1.使用Comparable接口进行排序时,需要对对象本身进行操作,实现Comparable接口并重写compareTo()方法,对代码侵入性较大,耦合度高。不推荐使用。
2.使用Comparator接口进行排序时,无需变动对象本身,侵入性小,耦合度低,同时还具有多样性,可以定制多种排序规则。nice!强烈推荐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值