Java 自然排序与比较器排序

自然排序与比较器排序

自然排序(Comparable)

java.lang.Comparable;

Comparable是一个抽象类,需要类实现它,才可以使用自然排序。 Comparable 同时是泛型,需要实现它的public int compareTo()方法.

以TreeSet举例,TreeSet有两种使用排序的方法,一种是类型自带自然排序接口Comparable,如:Integer,String等,都是实现了Comparable接口,所以可以直接添加对象进TreeSet中,TreeSet通过他们本身自带的compareTo()接口实现Set的有序排序;

        //TreeSet的无参构造方法,使用了其包含的类中的Comparable接口实现排序
        TreeSet<Student> ts = new TreeSet<Student>();
        /**
         * class Student implements Comparable<Student>{
         *     private int age;
         *
         *     @Override
         *     public int compareTo(Student s) {
         *         return 0;
         *     }
         * }
         * */
        //Student类中本身没有实现Comparable接口,我们可以自定义Comparable接口,实现我们想要的排序规则。

TreeSet中使用自然排序,会将当前对象和上一个对象进行比较。

    @Override
    public int compareTo(Student s) {
        //当前对象和上一个对象
        //当前对象的年龄减去上一个对象的年龄
        int num = this.age - s.age;
        //如果结果是一个整数,那么代表当前年龄大于上一个年龄,返回正数,这时候就会将当前对象添加到TreeSet中
        //因为是整数,TreeSet就默认添加到上一个元素的后面,也就是直接插入
        //这样判断就构成了升序的排序
        //如果返回的是一个负数,那么代表当前对象小于上一个对象,就会将当前对象插入到上一个对象之前,以此来保证升序
        return num;
    }

如果要使TreeSet完成降序的操作(从高到底):

    @Override
    public int compareTo(Student s) {
        //当前对象和上一个对象
        //上一个对象减去当前对象,如果是整数,那么代表上一个对象大于当前对象
        int num = s.age - this.age;
        //这时候是整数,那么就会将当前的元素添加到上一个元素之后,就完成了降序的排序(从高到低)
        //如果得到的是一个负数,那么就代表上一个元素小于当前元素,所以就会将当前元素添加到上一个元素之前,以此来保证有序
        return num;
    }

如果得到的结果是0呢?那么TreeSet就认为比较的两个是相同的对象,就不会进行添加操作。

总结:自然排序接口就是通过类来实现排序接口,使得类在需要排序的地方可以直接使用类的排序方法进行排序,但这种排序方式是固定的,也就是这个类只能使用该排序方法进行排序,如果想要不同方法来对这个类进行排序就无法实现。

比较器排序(Compareator)

java.util.Comparator

Comparator比较器排序,它的好处就是将类和自然排序进行了分离,在要使用到排序的时候,在创建对象的时候给它提供一个比较器即可。

以TreeSet举例,通过匿名内部类的方法创建比较器:

        //TreeSet的有参构造方法,通过提供比较器排序来实现TreeSet的排序,这样TreeSet的实现类就无需实现自然排序接口
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            //以匿名内部类方式在创建TreeSet对象的时候提供比较器
            @Override
            public int compare(Student s1, Student s2) {
                //s1就是当前的对象,s2就是TreeSet中的上一个对象
                //还是拿当前对象和上一个对象进行比较
                int num = s1.getAge() - s2.getAge();
                //当前对象的年龄减去上一个对象的年龄
                //如果是正数,那么代表当前对象大于上一个对象,
                //就会将当前对象添加到上一个对象之后,也就是直接插入到TreeSet的末尾
                return num;
            }
        });

比较器使用的升序排序(从低到高),如果想要使用降序,那么上一个对象的具体值减去当前对象的具体值即可完成降序排序,如:

        //TreeSet的有参构造方法,通过提供比较器排序来实现TreeSet的排序,这样TreeSet的实现类就无需实现自然排序接口
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            //以匿名内部类方式在创建TreeSet对象的时候提供比较器
            @Override
            public int compare(Student s1, Student s2) {
                //s1就是当前的对象,s2就是TreeSet中的上一个对象
                //还是上一个对象和当前对象进行比较
                int num = s2.getAge() - s1.getAge();
                //当前上一个对象的年龄减去当前对象的年龄
                //如果是正数,那么代表上一个对象大于当前对象
                //就会将当前对象添加到上一个对象之后,也就是直接插入到TreeSet的末尾
                //这样就实现了降序的排序
                return num;
            }
        });

同自然排序一样,如果返回的是0,那么TreeSet就认为是相同元素,就不进行添加,这就是TreeSet能实现排序和去重的要点。

Java 8 的Lambda语法,简化操作:

假设我们有一个List,需要实现将其中的元素进行降序排序,我们可用通过Collections.sort方法来排序List,同时提供一个比较器进行升序的排序,下面贴上代码:

正常new一个比较器:

import java.util.*;
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for(int i = 1;i<20;i++) {
            list.add(i);
        }

        //使用Collections工具类进行排序
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });

        //打印查看list中的元素排序方式
        System.out.println(list);
    }
}

结果:
在这里插入图片描述
实现了升序排序。

接下来我们使用Lambda语法:

import java.util.*;
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for(int i = 1;i<20;i++) {
            list.add(i);
        }

        //使用Collections工具类进行排序
        Collections.sort(list,(o1,o2)->o2-o1);

        //打印查看list中的元素排序方式
        System.out.println(list);
    }
}

结果:
在这里插入图片描述
同样实现了升序排序。

我们发现,可用使用Java 8提供的Lambda语法,简化我们new比较器的操作,其中第一个括号里面放的就是我们重写compare方法的两个参数,第二个括号就是我们compare方法中的返回值即可。

总结

    比较器排序不需要类实现自然排序接口,可以通过提供比较器的方法提供比较规则,无需该类实现自然排序接口。
    也就是该类可以使用比较器来实现多种比较排序,可以使用多种排序规则进行该类的排序。也就是将比较排序算法与具体的类分离开了,这样避免了一个类只能使用一种比较排序的算法。
    使得我们可以根据使用情况选择比较规则。

参考资料:
(6条消息) Java中的排序比较方式:自然排序和比较器排序_littledownload的博客-CSDN博客)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>