欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java进阶|比较器Comparable和Comparator

程序员文章站 2022-03-10 17:08:01
...

java进阶|比较器Comparable和Comparator

一,可能对于java的coder来说,这个点很简单,但对于我来说又是很难,想写这篇文章也是很久了,今天就以自己的理解来看下这两个接口,首先我们先看下Comparable接口的结构图。

java进阶|比较器Comparable和Comparator

这个比较接口只包含了一个compareTo()方法的接口,Comparable是一个排序接口,当我们定义的类实现了该接口,就说明了该类支持排序。

我们通过x.compareTo(y)来比较x和y的大小。若返回负数,则x比y小,若返回0,则x=y,若返回整数,则x大于y。

二,这里,自己去编写一个静态内部类来进行测试Comparable接口的使用。

package com.wpw.springbootjuc.java8.map;


import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;


import java.util.Collections;
import java.util.List;


/**
 * Comparable接口
 *
 * @author wpw
 */
@Slf4j
public class ComparableTest {
    public static void main(String[] args) {
        List<Person> personList = Lists.newArrayList();
        getPersonList(personList);
        System.out.println("Before Sort");
        acceptAndPrint(personList);
        Collections.sort(personList);
        System.out.println("After Sort");
        acceptAndPrint(personList);


    }


    private static void acceptAndPrint(List<Person> personList) {
        personList.stream().forEach(x -> {
            System.out.println(String.format("Id:%d,Name:%s,Age:%d", x.getId(), x.getName(), x.getAge()));
        });
        System.out.println();
    }


    /**
     * @return 数据集合,这里就简单模拟一下
     */
    private static void getPersonList(List<Person> personList) {
        personList.add(Person.builder().build().setId(3).setName("John").setAge(18));
        personList.add(Person.builder().build().setId(1).setName("Tom").setAge(20));
        personList.add(Person.builder().build().setId(2).setName("Marry").setAge(21));
    }




}


@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Accessors(chain = true)
class Person implements Comparable<Person> {
    private Integer id;
    private String name;
    private Integer age;


    /**
     * @param o 待比较的对象
     * @return 比较的值-1,0,1
     */
    @Override
    public int compareTo(Person o) {
        return this.id - o.id;
    }
}


排序前后输出的结果信息:

Before Sort
Id:3,Name:John,Age:18
Id:1,Name:Tom,Age:20
Id:2,Name:Marry,Age:21


After Sort
Id:1,Name:Tom,Age:20
Id:2,Name:Marry,Age:21
Id:3,Name:John,Age:18

三,接下来看下Comparator接口的结构图,这就是一个函数式接口,函数式接口就是只有一个方法,但是它可以有其它的默认方法。

java进阶|比较器Comparable和Comparator

四,下面的这张图就是Comparator接口包含的所有方法,大部分的都是default方法。

java进阶|比较器Comparable和Comparator

这里编写了一个示例程序用于测试Comparator接口的使用,Comparator为比较器接口,若要实现某个本身不支持排序的类,可以通过定义一个Comparator接口来实现类的排序。

package com.wpw.springbootjuc.java8.map;


import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;


import java.util.Collections;
import java.util.Comparator;
import java.util.List;


/**
 * Comparator接口
 *
 * @author wpw
 */
public class ComparatorTest {
    public static void main(String[] args) {
        List<Student> studentList = Lists.newArrayList();
        getStudentList(studentList);
        System.out.println("Before Sort");
        acceptAndPrint(studentList);
        Collections.sort(studentList, new MyComparator());
        System.out.println("After Sort");
        acceptAndPrint(studentList);
    }


    private static void acceptAndPrint(List<Student> studentList) {
        studentList.stream().forEach(x -> {
            System.out.println(String.format("Id:%d,Name:%s,Age:%d", x.getId(), x.getName(), x.getAge()));
        });
        System.out.println();
    }


    /**
     * @return 数据集合,这里就简单模拟一下
     */
    private static void getStudentList(List<Student> studentList) {
        studentList.add(Student.builder().build().setId(3).setName("John").setAge(18));
        studentList.add(Student.builder().build().setId(1).setName("Tom").setAge(20));
        studentList.add(Student.builder().build().setId(2).setName("Marry").setAge(21));
    }


    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @Builder
    @Accessors(chain = true)
    static class Student {
        private Integer id;
        private String name;
        private Integer age;
    }


    /**
     * 自定义比较器接口
     */
    static class MyComparator implements Comparator<Student> {


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


        @Override
        public boolean equals(Object obj) {
            return super.equals(obj);
        }
    }
}


五,以上就是Comparable和Comparator接口都是用来实现集合中元素的比较和排序的,当我们自己定义的一个类需要进行排序时,就要考虑实现Comparable或者Comparator接口,这样就可以根据指定的属性进行排序。

六,何时使用Comparable接口,何时使用Comparator接口?当我们在对要排序的排序规则比较固定,则考虑使用Comparable接口,若要对排序的类的排序规则是经常变化的,那我们就考虑使用Comparator接口。