Comparator 和 Comparable比较

Comparable是排序接口: 若一个类实现了Comparable接口,就意味着“该类支持排序”。

Comparator是比较器: 我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

我们需要创建一个包含了用户列表的 List 集合,并按用户的年龄从大到小进行排序,具体实现代码如下: 第一种:实现Comparable<>接口

 写一个Person类:

class Person implements Comparable{

        Integer id;
        String name;
        Integer age;

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

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

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }
        @Override
        public String toString() {
            return "Person{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
        @Override
        public int compareTo(Person o) {
            //按照年龄从大到小排序
            return o.getAge()-this.getAge();
        }
    }

实现结果测试:

public static void main(String[] args){
        //假设放进去三个对象,直接调用
        List pr=new ArrayList(){{
            add(new Person(1,"huitao1",32));
            add(new Person(2,"huitao2",40));
            add(new Person(3,"huitao3",28));

        }};
        //很重要
        Collections.sort(pr);
        pr.forEach(p->{
            System.out.print(p);
        });
    }

结果按照40、32、28进行了排序 

 第二种: Comparator 排序

Comparable 是类内部的比较方法,而 Comparator 是排序类外部的比较器。使用 Comparator 比较器,无需修改原 Person 类,只需要扩充一个 Person 类的比较器就行了,Comparator 的实现方法有以下两种:

  • 新建 Comparator 比较器;
  • 使用 Comparator 匿名类比较器。

 

static class Person {

        Integer id;
        String name;
        Integer age;

        public Person(Integer id, String name, Integer age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

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

        public Integer getAge() {
            return age;
        }

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

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

编写一个比较器类: 

static class ToPerson implements Comparator{

        @Override
        public int compare(Person o1, Person o2) {
            return o1.getAge() - o2.getAge();
        }
    }
public static void main(String[] args){



        List pr=new ArrayList(){{
            add(new Person(1,"huitao1",32));
            add(new Person(2,"huitao2",40));
            add(new Person(3,"huitao3",28));

        }};
        //很重要
        Collections.sort(pr,new ToPerson());
        pr.forEach(p->{
            System.out.print(p);
        });
    }

测试结果:

分别为28、32、40,如果要从大到小,可以编写为

static class ToPerson implements Comparator{

    @Override
    public int compare(Person o1, Person o2) {
        return o2.getAge() - o1.getAge();
    }
}

以匿名类的方式访问:

static class Person {

        Integer id;
        String name;
        Integer age;

        public Person(Integer id, String name, Integer age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

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

        public Integer getAge() {
            return age;
        }

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

        @Override
        public String toString() {
            return "Person{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
 public static void main(String[] args){



        List pr=new ArrayList(){{
            add(new Person(1,"huitao1",32));
            add(new Person(2,"huitao2",40));
            add(new Person(3,"huitao3",28));

        }};
        //很重要
        Collections.sort(pr, new Comparator() {
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge() - o1.getAge();
            }
        });
        pr.forEach(p->{
            System.out.print(p);
        });
    }

第三种:使用 Stream 流排序 

public static void main(String[] args){



        List pr=new ArrayList(){{
            add(new Person(1,"huitao1",32));
            add(new Person(2,"huitao2",40));
            add(new Person(3,"huitao3",28));

        }};
        pr= pr.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());
        pr.forEach(p->{
            System.out.print(p);
        });
    }
    static class Person {

        Integer id;
        String name;
        Integer age;

        public Person(Integer id, String name, Integer age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

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

        public Integer getAge() {
            return age;
        }

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

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

 

 stream()如果排序属性出现null,报告空指针个错误,解决办法

public static void main(String[] args){



        List pr=new ArrayList(){{
            add(new Person(1,"huitao1",32));
            add(new Person(2,"huitao2",40));
            add(new Person(3,"huitao3",28));
            add(new Person(4,"huitao3",null));

        }};
        pr= pr.stream().sorted(Comparator.comparing(Person::getAge,Comparator.nullsFirst(Integer::compareTo)).reversed()).collect(Collectors.toList());
        pr.forEach(p->{
            System.out.print(p);
        });
    }
    static class Person {

        Integer id;
        String name;
        Integer age;

        public Person(Integer id, String name, Integer age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

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

        public Integer getAge() {
            return age;
        }

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

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

 

Comparator.nullsFirst 表示将排序字段中的 null 值放到集合最前面,如果想要将 null 值放到集合最后面可以使用 Comparator.nullsLast。 

你可能感兴趣的:(【Java算法】,java)