Java中Comparable<T>与Comparator<T>的使用——对数组中数据进行自定义排序

        Comparable<T>和Comparator<T>是Java中适用于不同情景下的用来对数据进行比较(排序)的两个接口。

下面举例展示Comparable接口的使用:

情景:有一个存放6个student的数组,每个student有age、name、number三个属性,要求按照number升序,age降序,name按字符串长度升序 的规则对数组中的student进行排序。

代码演示:

定义一个Student类,实现Comparable<T>接口,重写comparaTo方法,在方法中制定规则

class Student implements Comparable<Student> {
    private int age;
    private int number;
    private String name;

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

    public Student() {
    }

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

    @Override
    /**
     * number升序
     * age降序
     * name按长度升序
     */
    public int compareTo(Student o) {
        int i = this.number - o.number;
        int j = this.age - o.age;
        int k = this.name.length()-o.name.length();
        return i != 0 ? i : (j != 0 ? -j : k);
    }
}

关于compareTo方法的使用规则:

this可以看成前面已经经过比较的数据,o可以看成后面新来的将要进行比较的数据。返回正数则表示o因该排在this前面,返回负数则表示o应该排在this后面,返回0则表示两个没有前后之分。若方法体中只写return一个正数,则这组数据排列顺序不变,如果只写return一个负数,则将原来的排列顺序进行反转。(例子中采用三目运算符进行逻辑判断,也可以采用if()语句)

下面定义测试类检验排序结果:

public class ComparableDemo {
    public static void main(String[] args) {
        //创建学生并放入数组
        Student[] stuArr = {
                new Student(18, 101, "张三"),
                new Student(18, 101, "张三子"),
                new Student(19, 101, "李四"),
                new Student(19, 102, "张四"),
                new Student(18, 103, "张十三"),
                new Student(17, 103, "王五")
        };
        //调用java.util.Arrays.sort方法
        java.util.Arrays.sort(stuArr);
        for (Student student : stuArr) {
            System.out.println(student);
        }
    }
}

运行结果:

Java中Comparable<T>与Comparator<T>的使用——对数组中数据进行自定义排序


 


下面举例展示Comparator接口的使用:

情景:有一个存放6个student的数组,每个student有age、name、number三个属性。

需求一:按照number、age、name依次升序排序

需求二:按照number、age、name依次降序排序

需求三:按照number升序,age降序,name按字典顺序排序

······

要求所有需求都在同一个测试类中实现。

代码演示:

·定义学生类:(该类只是一个普通的学生类,没有实现任何接口)

  • class Student2 {
        private int age;
        private int number;
        private String name;
    
        public Student2(int age, int number, String name) {
            this.age = age;
            this.number = number;
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public int getNumber() {
            return number;
        }
    
        public String getName() {
            return name;
        }
    
        public Student2() {
        }
    
        @Override
        public String toString() {
            return "Student2{" +
                    "age=" + age +
                    ", number=" + number +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
·接下来定义比较器类,实现Comparator接口,重写compare方法。
ComparatorMachine01用来实现需求一;ComparatorMachine03用来实现需求三;需求二我们将比较器类写成内部类形式或Lambda表达式来实现。比较器类须实现Comparator<T>接口,T为比较对象的数据类型。
/**
 * 比较器01
 * 所有内容升序排序
 */
class ComparatorMachine01 implements Comparator<Student2> {
    @Override
    public int compare(Student2 o1, Student2 o2) {
        int i = o1.getNumber() - o2.getNumber();
        int j = o1.getAge() - o2.getAge();
        int k = o1.getName().compareTo(o2.getName());
        return i != 0 ? i : (j != 0 ? j : k);
    }
}

/**
 * 比较器03
 */
class ComparatorMachine03 implements Comparator<Student2> {
    @Override
    public int compare(Student2 o1, Student2 o2) {
        int i = o1.getNumber() - o2.getNumber();
        int j = o1.getAge() - o2.getAge();
        int k = o1.getName().compareTo(o2.getName());
        //返回正数则排序时o2放前面;返回负数则o2放后面
        return i != 0 ? i : (j != 0 ? -j : k);
    }
}

关于compare方法的使用规则:

o1和o2为两个将要进行比较的数据。返回正数则表示o2因该排在o1前面,返回负数则表示o2应该排在o1后面,返回0则表示两个没有前后之分。若方法体中只写return一个正数,则这组数据排列顺序不变,如果只写return一个负数,则将原来的排列顺序进行反转。

(name采用String类的compareTo方法,即按照字符在字典中的顺序排序。)

·接下来写一个测试类实现上述需求:

public class ComparatorDemo {
    public static void main(String[] args) {
        Student2[] stuArr2 = {
                new Student2(18, 101, "张三"),
                new Student2(18, 101, "张三子"),
                new Student2(19, 101, "李四"),
                new Student2(19, 102, "张四"),
                new Student2(18, 103, "张十三"),
                new Student2(17, 103, "王五")
        };
        //调用java.util.Arrays.sort方法,传入待排序的数组和符合需求的比较器对象
        Arrays.sort(stuArr2, new ComparatorMachine01());//调用比较器01 实现升序排序
        for (Student2 student : stuArr2) {
            System.out.println(student);
        }
        System.out.println();
        //采用Lambda表达式
        Arrays.sort(stuArr2, (o1, o2) -> {
            int i = o1.getNumber() - o2.getNumber();
            int j = o1.getAge() - o2.getAge();
            int k = o1.getName().compareTo(o2.getName());
            return i != 0 ? -i : (j != 0 ? -j : -k);
        });
       /* 等价于下面代码(以内部类形式)
            Arrays.sort(stuArr2, new Comparator<Student2>() {
            @Override
            public int compare(Student2 o1, Student2 o2) {
                int i = o1.getNumber() - o2.getNumber();
                int j = o1.getAge() - o2.getAge();
                int k = o1.getName().compareTo(o2.getName());
                return i != 0 ? -i : (j != 0 ? -j : -k);
            }
        });*/
        for (Student2 student : stuArr2) {
            System.out.println(student);
        }
        System.out.println();
        //调用比较器03 实现number升序,age降序,name升序
        Arrays.sort(stuArr2, new ComparatorMachine03());
        for (Student2 student : stuArr2) {
            System.out.println(student);
        }
    }
}

运行结果:

Java中Comparable<T>与Comparator<T>的使用——对数组中数据进行自定义排序

我们可以发现,如果需要对一组数据进行多种规则的排序,选择Comparator接口更合适。 

(文章略显粗糙,若有错误,烦请批评指正!)

 

上一篇:按照list中实体类的某一属性排序


下一篇:AEnM:原位电化学AFM揭示H2O介导的锂氧界面反应机制