Java 示例中的比较器和比较器

Java中的COMPARIBLE和COMPARATOR对于对象集合的排序非常有用。Java提供了一些内置的方法来对基元类型、数组或包装类、数组或列表进行排序。在这里,我们将首先学习如何对基元类型和包装类的数组/列表进行排序,然后我们将使用java.lang.Compable 和** java.util.Compator** 接口对自定义类的数组/列表进行排序。让我们看看如何用一个简单的程序对基元类型或对象数组和列表进行排序。

 1package com.journaldev.sort;
 2
 3import java.util.ArrayList;
 4import java.util.Arrays;
 5import java.util.Collections;
 6import java.util.List;
 7
 8public class JavaObjectSorting {
 9
10    /**
11     * This class shows how to sort primitive arrays, 
12     * Wrapper classes Object Arrays
13     * @param args
14     */
15    public static void main(String[] args) {
16        //sort primitives array like int array
17        int[] intArr = {5,9,1,10};
18        Arrays.sort(intArr);
19        System.out.println(Arrays.toString(intArr));
20
21        //sorting String array
22        String[] strArr = {"A", "C", "B", "Z", "E"};
23        Arrays.sort(strArr);
24        System.out.println(Arrays.toString(strArr));
25
26        //sorting list of objects of Wrapper classes
27        List<String> strList = new ArrayList<String>();
28        strList.add("A");
29        strList.add("C");
30        strList.add("B");
31        strList.add("Z");
32        strList.add("E");
33        Collections.sort(strList);
34        for(String str: strList) System.out.print(" "+str);
35    }
36}

上述程序的输出为:

1[1, 5, 9, 10]
2[A, B, C, E, Z]
3 A B C E Z

现在,让我们尝试对对象数组进行排序。

 1package com.journaldev.sort;
 2
 3public class Employee {
 4
 5    private int id;
 6    private String name;
 7    private int age;
 8    private long salary;
 9
10    public int getId() {
11        return id;
12    }
13
14    public String getName() {
15        return name;
16    }
17
18    public int getAge() {
19        return age;
20    }
21
22    public long getSalary() {
23        return salary;
24    }
25
26    public Employee(int id, String name, int age, int salary) {
27        this.id = id;
28        this.name = name;
29        this.age = age;
30        this.salary = salary;
31    }
32
33    @Override
34    //this is overridden to print the user-friendly information about the Employee
35    public String toString() {
36        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
37                this.salary + "]";
38    }
39
40}

下面是我用来对Employee对象数组进行排序的代码。

 1//sorting object array
 2Employee[] empArr = new Employee[4];
 3empArr[0] = new Employee(10, "Mikey", 25, 10000);
 4empArr[1] = new Employee(20, "Arun", 29, 20000);
 5empArr[2] = new Employee(5, "Lisa", 35, 5000);
 6empArr[3] = new Employee(1, "Pankaj", 32, 50000);
 7
 8//sorting employees array using Comparable interface implementation
 9Arrays.sort(empArr);
10System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));

当我试图运行它时,它抛出以下运行时异常。

1Exception in thread "main" java.lang.ClassCastException: com.journaldev.sort.Employee cannot be cast to java.lang.Comparable
2    at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
3    at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
4    at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
5    at java.util.Arrays.sort(Arrays.java:472)
6    at com.journaldev.sort.JavaSorting.main(JavaSorting.java:41)

可比较和比较器

comparable and comparator,comparable vs comparator,comparable and comparator in javaJava提供了 Comparable 接口,如果我们想使用[Arrays](/community/tutorials/java-arrays-java-util-arrays)或[Collections](/community/tutorials/collections-class-java-util-collections)排序方法,任何自定义类都应该实现这个接口。Comparable接口有** compareTo(T obj)** 方法,用于排序方法,您可以检查任何Wrapper,String或Date类来确认这一点。我们应该重写这个方法,如果)之后,这里是生成的Employee类。

 1package com.journaldev.sort;
 2
 3import java.util.Comparator;
 4
 5public class Employee implements Comparable<Employee> {
 6
 7    private int id;
 8    private String name;
 9    private int age;
10    private long salary;
11
12    public int getId() {
13        return id;
14    }
15
16    public String getName() {
17        return name;
18    }
19
20    public int getAge() {
21        return age;
22    }
23
24    public long getSalary() {
25        return salary;
26    }
27
28    public Employee(int id, String name, int age, int salary) {
29        this.id = id;
30        this.name = name;
31        this.age = age;
32        this.salary = salary;
33    }
34
35    @Override
36    public int compareTo(Employee emp) {
37        //let's sort the employee based on an id in ascending order
38        //returns a negative integer, zero, or a positive integer as this employee id
39        //is less than, equal to, or greater than the specified object.
40        return (this.id - emp.id);
41    }
42
43    @Override
44    //this is required to print the user-friendly information about the Employee
45    public String toString() {
46        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
47                this.salary + "]";
48    }
49
50}

现在,当我们为雇员的数组排序执行上面的代码片段并打印它时,输出如下。

1Default Sorting of Employees list:
2[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]

如您所见,Employees数组按id按升序排序。但是,在大多数现实场景中,我们希望基于不同的参数进行排序。例如,作为首席执行官,我希望根据工资对员工进行排序,而人力资源部则希望根据年龄对员工进行排序。这就是我们需要使用Java比较器 接口的情况,因为_Compable.CompareTo(Object O)_方法实现可以提供默认排序,而我们不能动态更改它。而使用比较器,我们可以定义具有不同排序方式的多个方法,然后根据我们的需求选择排序方法。

Java比较器

比较器interface compare(Object o 1,Object o2) method需要实现,它接受两个Object参数,如果第一个参数小于第二个参数,它应该以这样一种方式实现,如果它们相等,则返回负整数,如果第一个参数大于第二个参数,则返回正整数。Comparable和Comparator接口使用泛型进行编译时类型检查,详细了解[Java泛型](/community/tutorials/java-generics-example-method-class-interface)。下面是我们如何在Employee类中创建不同的Comparator实现。

 1/**
 2     * Comparator to sort employees list or array in order of Salary
 3     */
 4    public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {
 5
 6        @Override
 7        public int compare(Employee e1, Employee e2) {
 8            return (int) (e1.getSalary() - e2.getSalary());
 9        }
10    };
11
12    /**
13     * Comparator to sort employees list or array in order of Age
14     */
15    public static Comparator<Employee> AgeComparator = new Comparator<Employee>() {
16
17        @Override
18        public int compare(Employee e1, Employee e2) {
19            return e1.getAge() - e2.getAge();
20        }
21    };
22
23    /**
24     * Comparator to sort employees list or array in order of Name
25     */
26    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {
27
28        @Override
29        public int compare(Employee e1, Employee e2) {
30            return e1.getName().compareTo(e2.getName());
31        }
32    };

以上所有比较器接口的实现都是**匿名classes** .我们可以使用这些比较器将参数传递给数组和集合类的排序函数。

 1//sort employees array using Comparator by Salary
 2Arrays.sort(empArr, Employee.SalaryComparator);
 3System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));
 4
 5//sort employees array using Comparator by Age
 6Arrays.sort(empArr, Employee.AgeComparator);
 7System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));
 8
 9//sort employees array using Comparator by Name
10Arrays.sort(empArr, Employee.NameComparator);
11System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));

以下是上述代码片段的输出:

1Employees list sorted by Salary:
2[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
3Employees list sorted by Age:
4[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
5Employees list sorted by Name:
6[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]

所以现在我们知道,如果我们想要对Java对象数组或列表进行排序,我们需要实现Java可比较接口来提供默认排序,我们应该实现Java比较器接口来提供不同的排序方式。我们也可以创建单独的类来实现`Compator‘接口,然后使用它。以下是我们在Java中解释比较和比较 的最后几个类。

 1package com.journaldev.sort;
 2
 3import java.util.Comparator;
 4
 5public class Employee implements Comparable<Employee> {
 6
 7    private int id;
 8    private String name;
 9    private int age;
10    private long salary;
11
12    public int getId() {
13        return id;
14    }
15
16    public String getName() {
17        return name;
18    }
19
20    public int getAge() {
21        return age;
22    }
23
24    public long getSalary() {
25        return salary;
26    }
27
28    public Employee(int id, String name, int age, int salary) {
29        this.id = id;
30        this.name = name;
31        this.age = age;
32        this.salary = salary;
33    }
34
35    @Override
36    public int compareTo(Employee emp) {
37        //let's sort the employee based on an id in ascending order
38        //returns a negative integer, zero, or a positive integer as this employee id
39        //is less than, equal to, or greater than the specified object.
40        return (this.id - emp.id);
41    }
42
43    @Override
44    //this is required to print the user-friendly information about the Employee
45    public String toString() {
46        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
47                this.salary + "]";
48    }
49
50    /**
51     * Comparator to sort employees list or array in order of Salary
52     */
53    public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {
54
55        @Override
56        public int compare(Employee e1, Employee e2) {
57            return (int) (e1.getSalary() - e2.getSalary());
58        }
59    };
60
61    /**
62     * Comparator to sort employees list or array in order of Age
63     */
64    public static Comparator<Employee> AgeComparator = new Comparator<Employee>() {
65
66        @Override
67        public int compare(Employee e1, Employee e2) {
68            return e1.getAge() - e2.getAge();
69        }
70    };
71
72    /**
73     * Comparator to sort employees list or array in order of Name
74     */
75    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {
76
77        @Override
78        public int compare(Employee e1, Employee e2) {
79            return e1.getName().compareTo(e2.getName());
80        }
81    };
82}

下面是比较器接口的单独类实现,它将首先比较两个Employees对象的id,如果它们相同,则比较它们的名字。

 1package com.journaldev.sort;
 2
 3import java.util.Comparator;
 4
 5public class EmployeeComparatorByIdAndName implements Comparator<Employee> {
 6
 7    @Override
 8    public int compare(Employee o1, Employee o2) {
 9        int flag = o1.getId() - o2.getId();
10        if(flag==0) flag = o1.getName().compareTo(o2.getName());
11        return flag;
12    }
13
14}

下面是测试类,我们在其中使用不同的方法来使用可比较和比较器对Java中的对象进行排序。

 1package com.journaldev.sort;
 2
 3import java.util.Arrays;
 4
 5public class JavaObjectSorting {
 6
 7    /**
 8     * This class shows how to sort custom objects array/list
 9     * implementing Comparable and Comparator interfaces
10     * @param args
11     */
12    public static void main(String[] args) {
13
14        //sorting custom object array
15        Employee[] empArr = new Employee[4];
16        empArr[0] = new Employee(10, "Mikey", 25, 10000);
17        empArr[1] = new Employee(20, "Arun", 29, 20000);
18        empArr[2] = new Employee(5, "Lisa", 35, 5000);
19        empArr[3] = new Employee(1, "Pankaj", 32, 50000);
20
21        //sorting employees array using Comparable interface implementation
22        Arrays.sort(empArr);
23        System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));
24
25        //sort employees array using Comparator by Salary
26        Arrays.sort(empArr, Employee.SalaryComparator);
27        System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));
28
29        //sort employees array using Comparator by Age
30        Arrays.sort(empArr, Employee.AgeComparator);
31        System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));
32
33        //sort employees array using Comparator by Name
34        Arrays.sort(empArr, Employee.NameComparator);
35        System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));
36
37        //Employees list sorted by ID and then name using Comparator class
38        empArr[0] = new Employee(1, "Mikey", 25, 10000);
39        Arrays.sort(empArr, new EmployeeComparatorByIdAndName());
40        System.out.println("Employees list sorted by ID and Name:\n"+Arrays.toString(empArr));
41    }
42
43}

下面是上述程序的输出:

 1Default Sorting of Employees list:
 2[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]
 3Employees list sorted by Salary:
 4[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
 5Employees list sorted by Age:
 6[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
 7Employees list sorted by Name:
 8[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]
 9Employees list sorted by ID and Name:
10[[id=1, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000]]

java.lang.Compare 和** java.util.Compator** 是两个强大的接口,可以用来在Java中提供对象排序。

对比VS比较器

1.可比接口可以提供单一的排序方式,而比较器接口可以提供不同的排序方式。 2.对于使用可比较类,Class需要实现它,而对于使用比较器,我们不需要对类进行任何更改。 3.比较接口在java.lang包中,而比较接口在java.util包中。 4.我们不需要在客户端做任何代码修改,使用可比较的、Arrays.sort()Collection.ort()方法会自动使用类的CompareTo()方法。对于比较器,客户端需要提供在Compare()方法中使用的比较器类。

您知道接受比较器参数的Collections.ort()方法遵循Strategy Pattern吗?

您可以从我们的giHub Repository.]签出完整的代码和更多的核心Java示例

Published At
Categories with 技术
Tagged with
comments powered by Disqus