2021/11/18 西安 Comparable自然排序和Comparator定制排序

Comparable

比较对象大小

Comparable 接口和 Comparator 接口都是 Java 中用于排序的接口,它们在实现类对象之间比较大小、排序等方面发挥了重要作用:

  • Comparable 接口实际上是出自java.lang包 它有一个 compareTo(Object obj)方法用来排序
  • Comparator接口实际上是出自 java.util 包它有一个compare(Object obj1, Object obj2)方法用来排序

比较对象大小的经典应用---排序 

如果在使用 Arrays.sort( 数组 )
或Collections.sort(Collection 集合 ) 方法时,
TreeSet TreeMap时元素默认按照Comparable 比较规则排序;
也可以单独为 Arrays.sort( 数组 )
或 Collections.sort(Collection集合 ) 方法,
TreeSet TreeMap 指定 Comparator 定制比较器对象。
对象之间要想比大小比出个所以然,要求创建对象的类必须是Comparable接口的实现类

原则:在使用Collection的sort排序的集合元素都必须是Comparable接口的实现类,表示该类是可以比较的。


Comparable(Integer、String)

String、包装类都已经实现了Comparable接口,并且重写了compareTo()方法。我们是可以直接使用的。

//comparable接口
public interface Comparable<T> {
    public int compareTo(T o);
}
    public static void main(String[] args) {
        //public final class Integer extends Number implements Comparable<Integer>
        List<Integer> list0 = new ArrayList<>();//Integer是隐藏伏笔,集合中只能存储引用类型
        for (int i = 0; i < 10; i++) {
            //随机生成1-100的整数
            int val = (int)(Math.random() * 100 + 1);
            list0.add(val);
        }
        System.out.println("list0集合排序前"+list0);//[75, 73, 29, 82, 42, 10, 99, 83, 85, 8]
        Collections.sort(list0);
        System.out.println("list0集合排序后"+list0);//[8, 10, 29, 42, 73, 75, 82, 83, 85, 99]
        System.out.println("=======================================");
        //public final class String implements java.io.Serializable, Comparable<String>, CharSequence
        List<String> list1 = new ArrayList<>();
        list1.add("Alive");
        list1.add("Rose");
        list1.add("Jack");
        list1.add("Noname");
        System.out.println("list1集合排序前"+list1);//[Alive, Rose, Jack, Noname]
        Collections.sort(list1);
        System.out.println("list1集合排序后"+list1);//[Alive, Jack, Noname, Rose]

    }

之所以能调用Collections.sort()对list集合排序是因为 Integer、String类都实现了Comparable接口,所以在对list0和list1集合排序时没有报错。

运行结果:


Comparable(Goods 商品类

我们自定义的类(Goods 商品类),也想调用Collections.sort()实现排序,那就必须在定义类的时实现Comparable接口,重写compareTo()方法。

重写compareTo(obj)的规则:

        如果当前对象this大于形参对象obj,则返回正整数。

        如果当前对象this小于形参对象obj,则返回负整数。

        如果当前对象this等于形参对象obj,则返回零。

public class Goods implements Comparable<Goods>{
    String name;
    Double price;

    public Goods() {
    }

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

    @Override
    public int compareTo(Goods goods) {
        //使商品的排序是按照价格从低到高排序
        if(this.price>goods.price){
            return 1;
        }else if(this.price<goods.price){
            return -1;
        }else {
            return 0;
        }
    }
}

测试:

    public static void main(String[] args) {
        Goods g1 = new Goods("毛巾", 12.8);
        Goods g2 = new Goods("牙刷", 5.6);
        Goods g3 = new Goods("洗面奶", 108.1);
        Goods g4 = new Goods("鞋刷", 1.3);
        ArrayList<Goods> list = new ArrayList<>();
        list.add(g1);
        list.add(g2);
        list.add(g3);
        list.add(g4);
        System.out.println("排序前:");
        for (Goods goods : list) {
            System.out.println("商品:"+goods.name+" ,价格"+goods.price);
        }
        System.out.println("==================================");
        Collections.sort(list);
        System.out.println("排序后:");
        for (Goods goods : list) {
            System.out.println("商品:"+goods.name+" ,价格"+goods.price);
        }

    }

运行结果:


那么,新的需求来了。

我要先把商品按照价格从低到高排序,要是价格一样的话,那就按照商品名称从低到高排序。

    public int compareTo(Goods goods) {
        //使商品的排序是按照价格从低到高排序
        if(this.price>goods.price){
            return 1;
        }else if(this.price<goods.price){
            return -1;
        }else {
            //商品名称是字符串嘛,直接调String类重写过的compareTo()方法,比较字符串大小
            return this.name.compareTo(goods.name);
        }
    }

Comparator定制排序

Comparator应用场景

public interface Comparator<T> {
    int compare(T o1, T o2);
}

是不是觉得学了comparable自然排序就够用了,虽然我也这么想,但是还不行(⊙o⊙)…。

某些情况还是需要用定制排序的。comparator应用的俩种情况,

  • 一种是人家写好你不能改的类,比如jdk啥的。
  • 另一种像String那样的已经实现过Comparable接口的。但是你不想使用人家写好的那种排序方式。

利用重写的方法 :int compare(T o1,T o2),比较o1和o2的大小:
如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2


Comparator(String)

Comparable像是一劳永逸,而Comparator就像是临时的,你会越来越有这种感觉的。

怎么使用Comparator接口呢?

实现接口,重写compare(Objet o1,Object o2)方法。注意Comparator也是函数式接口

如下,使用匿名内部类实现了Comparator接口,临时改变字符串默认排序规则。

    public static void main(String[] args) {
        String[] arr = {"AA", "DD", "BB", "CC"};
        System.out.println("排序前"+Arrays.toString(arr));
        Arrays.sort(arr, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //改变字符串排序规则,使得字符串从大到小排序
                return -o1.compareTo(o2);
            }
        });
        System.out.println("定制排序后"+Arrays.toString(arr));

    }



//可以使用lambda简化
    public static void main(String[] args) {
        String[] arr = {"AA", "DD", "BB", "CC"};
        System.out.println("排序前"+Arrays.toString(arr));
        Arrays.sort(arr, (o1, o2) -> {
            //改变字符串排序规则,使得字符串从大到小排序
            return -o1.compareTo(o2);
        });
        System.out.println("定制排序后"+Arrays.toString(arr));
    }

运行结果:


Comparator(Goods 商品类)

定制排序自定义的Goods类,临时改变排序规则:

使用定制排序改变默认的自然排序规则,我们让商品价格从高到低排序

    public static void main(String[] args) {
        Goods g1 = new Goods("毛巾", 12.8);
        Goods g2 = new Goods("牙刷", 5.6);
        Goods g3 = new Goods("洗面奶", 108.1);
        Goods g4 = new Goods("鞋刷", 1.3);
        ArrayList<Goods> list = new ArrayList<>();
        list.add(g1);
        list.add(g2);
        list.add(g3);
        list.add(g4);
        System.out.println("排序前:");
        for (Goods goods : list) {
            System.out.println("商品:"+goods.name+" ,价格"+goods.price);
        }
        System.out.println("==================================");
        Collections.sort(list);
        System.out.println("默认的自然排序后:");
        for (Goods goods : list) {
            System.out.println("商品:"+goods.name+" ,价格"+goods.price);
        }
        System.out.println("==================================");
        //使用定制排序改变默认的自然排序规则,我们让商品价格从高到低排序
        Collections.sort(list, new Comparator<Goods>() {
            @Override
            public int compare(Goods o1, Goods o2) {
                return -o1.compareTo(o2);
            }
        });
        System.out.println("定制排序后:");
        for (Goods goods : list) {
            System.out.println("商品:"+goods.name+" ,价格"+goods.price);
        }
    }

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值