Java示例中的Comparable和Comparator

Comparable and Comparator in Java are very useful for sorting the collection of objects. Java provides some inbuilt methods to sort primitive types array or Wrapper classes array or list. Here we will first learn how we can sort an array/list of primitive types and wrapper classes and then we will use java.lang.Comparable and java.util.Comparator interfaces to sort array/list of custom classes.

Java中的Comparable和Comparator对排序对象集合非常有用。 Java提供了一些内置方法来对原始类型数组或包装器类数组或列表进行排序。 在这里,我们将首先学习如何对基本类型和包装器类的数组/列表进行排序,然后将使用java.lang.Comparablejava.util.Comparator接口对自定义类的数组/列表进行排序。

Let’s see how we can sort primitive types or Object array and list with a simple program.

让我们看看如何使用简单的程序对原始类型或对象数组进行排序并列出。

package com.journaldev.sort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class JavaObjectSorting {

    /**
     * This class shows how to sort primitive arrays, 
     * Wrapper classes Object Arrays
     * @param args
     */
    public static void main(String[] args) {
        //sort primitives array like int array
        int[] intArr = {5,9,1,10};
        Arrays.sort(intArr);
        System.out.println(Arrays.toString(intArr));
        
        //sorting String array
        String[] strArr = {"A", "C", "B", "Z", "E"};
        Arrays.sort(strArr);
        System.out.println(Arrays.toString(strArr));
        
        //sorting list of objects of Wrapper classes
        List<String> strList = new ArrayList<String>();
        strList.add("A");
        strList.add("C");
        strList.add("B");
        strList.add("Z");
        strList.add("E");
        Collections.sort(strList);
        for(String str: strList) System.out.print(" "+str);
    }
}

Output of the above program is:

上面程序的输出是:

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

Now let’s try to sort an array of objects.

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

package com.journaldev.sort;

public class Employee {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    //this is overridden to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

}

Here is the code I used to sort the array of Employee objects.

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

//sorting object array
Employee[] empArr = new Employee[4];
empArr[0] = new Employee(10, "Mikey", 25, 10000);
empArr[1] = new Employee(20, "Arun", 29, 20000);
empArr[2] = new Employee(5, "Lisa", 35, 5000);
empArr[3] = new Employee(1, "Pankaj", 32, 50000);

//sorting employees array using Comparable interface implementation
Arrays.sort(empArr);
System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));

When I tried to run this, it throws the following runtime exception.

当我尝试运行此程序时,它将引发以下运行时异常。

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

可比和比较器 (Comparable and Comparator)

Java provides Comparable interface which should be implemented by any custom class if we want to use Arrays or Collections sorting methods.

Java提供了Comparable接口,如果我们要使用ArraysCollections排序方法,则可以由任何自定义类实现。

The Comparable interface has compareTo(T obj) method which is used by sorting methods, you can check any Wrapper, String or Date class to confirm this. We should override this method in such a way that it returns a negative integer, zero, or a positive integer if “this” object is less than, equal to, or greater than the object passed as an argument.

Comparable接口具有compareTo(T obj)方法,该方法由排序方法使用,您可以检查任何Wrapper,String或Date类来确认这一点。 如果“此”对象小于,等于或大于作为参数传递的对象,则应以使其返回负整数,零或正整数的方式覆盖此方法。

After implementing Comparable interface in Employee class, here is the resulting Employee class.

在Employee类中实现Comparable 接口之后,这里是生成的Employee类。

package com.journaldev.sort;

import java.util.Comparator;

public class Employee implements Comparable<Employee> {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee emp) {
        //let's sort the employee based on an id in ascending order
        //returns a negative integer, zero, or a positive integer as this employee id
        //is less than, equal to, or greater than the specified object.
        return (this.id - emp.id);
    }

    @Override
    //this is required to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

}

Now when we execute the above snippet for Arrays sorting of Employees and print it, here is the output.

现在,当我们对Employees进行数组排序并执行上面的代码片段并将其打印时,这是输出。

Default Sorting of Employees list:
[[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]]

As you can see that Employees array is sorted by id in ascending order.

如您所见,Employees数组按ID升序排列。

But, in most real-life scenarios, we want sorting based on different parameters. For example, as a CEO, I would like to sort the employees based on Salary, an HR would like to sort them based on age. This is the situation where we need to use Java Comparator interface because Comparable.compareTo(Object o) method implementation can provide default sorting and we can’t change it dynamically. Whereas with Comparator, we can define multiple methods with different ways of sorting and then chose the sorting method based on our requirements.

但是,在大多数实际场景中,我们希望基于不同的参数进行排序。 例如,作为首席执行官,我想根据工资对员工进行排序,而人力资源则想根据年龄对员工进行排序。 在这种情况下,我们需要使用Java Comparator接口,因为Comparable.compareTo(Object o)方法实现可以提供默认排序,并且我们不能动态更改它。 而使用Comparator,我们可以定义具有不同排序方式的多种方法,然后根据我们的要求选择排序方法。

Java比较器 (Java Comparator)

Comparator interface compare(Object o1, Object o2) method need to be implemented that takes two Object argument, it should be implemented in such a way that it returns negative int if the first argument is less than the second one and returns zero if they are equal and positive int if the first argument is greater than the second one.

需要实现带有两个Object参数的比较器接口compare(Object o1,Object o2)方法,该方法的实现方式是,如果第一个参数小于第二个参数,则返回负整数,如果第一个参数小于第二个,则返回零。如果第一个参数大于第二个参数,则等于和正整数。

Comparable and Comparator interfaces use Generics for compile-time type checking, learn more about Java Generics.

Comparable和Comparator接口使用泛型进行编译时类型检查,了解有关Java泛型的更多信息。

Here is how we can create different Comparator implementation in the Employee class.

这是我们如何在Employee类中创建不同的Comparator实现的方法。

/**
     * Comparator to sort employees list or array in order of Salary
     */
    public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return (int) (e1.getSalary() - e2.getSalary());
        }
    };

    /**
     * Comparator to sort employees list or array in order of Age
     */
    public static Comparator<Employee> AgeComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getAge() - e2.getAge();
        }
    };

    /**
     * Comparator to sort employees list or array in order of Name
     */
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };

All the above implementations of Comparator interface are anonymous classes.

上述Comparator接口的所有实现都是匿名类

We can use these comparators to pass an argument to sort function of Arrays and Collections classes.

我们可以使用这些比较器将参数传递给Arrays和Collections类的排序函数。

//sort employees array using Comparator by Salary
Arrays.sort(empArr, Employee.SalaryComparator);
System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));

//sort employees array using Comparator by Age
Arrays.sort(empArr, Employee.AgeComparator);
System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));

//sort employees array using Comparator by Name
Arrays.sort(empArr, Employee.NameComparator);
System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));

Here is the output of the above code snippet:

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

Employees list sorted by Salary:
[[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]]
Employees list sorted by Age:
[[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]]
Employees list sorted by Name:
[[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]]

So now we know that if we want to sort java object array or list, we need to implement java Comparable interface to provide default sorting and we should implement java Comparator interface to provide different ways of sorting.

因此,现在我们知道,如果要对java对象数组或列表进行排序,则需要实现java Comparable接口以提供默认排序,并且应该实现java Comparator接口以提供不同的排序方式。

We can also create separate class that implements Comparator interface and then use it.

我们还可以创建实现Comparator接口的单独类,然后使用它。

Here is the final classes we have explaining Comparable and Comparator in Java.

这是我们讲解Java中的Comparable和Comparator的最终课程。

package com.journaldev.sort;

import java.util.Comparator;

public class Employee implements Comparable<Employee> {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee emp) {
        //let's sort the employee based on an id in ascending order
        //returns a negative integer, zero, or a positive integer as this employee id
        //is less than, equal to, or greater than the specified object.
        return (this.id - emp.id);
    }

    @Override
    //this is required to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

    /**
     * Comparator to sort employees list or array in order of Salary
     */
    public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return (int) (e1.getSalary() - e2.getSalary());
        }
    };

    /**
     * Comparator to sort employees list or array in order of Age
     */
    public static Comparator<Employee> AgeComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getAge() - e2.getAge();
        }
    };

    /**
     * Comparator to sort employees list or array in order of Name
     */
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };
}

Here is the separate class implementation of Comparator interface that will compare two Employees object first on their id and if they are same then on the name.

这是Comparator接口的单独类实现,该实现将首先比较两个Employees对象的ID,如果它们相同,则将其名称进行比较。

package com.journaldev.sort;

import java.util.Comparator;

public class EmployeeComparatorByIdAndName implements Comparator<Employee> {

    @Override
    public int compare(Employee o1, Employee o2) {
        int flag = o1.getId() - o2.getId();
        if(flag==0) flag = o1.getName().compareTo(o2.getName());
        return flag;
    }

}

Here is the test class where we are using different ways to sort Objects in java using Comparable and Comparator.

这是测试类,在这里我们使用不同的方式使用Comparable和Comparator对Java中的对象进行排序。

package com.journaldev.sort;

import java.util.Arrays;

public class JavaObjectSorting {

    /**
     * This class shows how to sort custom objects array/list
     * implementing Comparable and Comparator interfaces
     * @param args
     */
    public static void main(String[] args) {

        //sorting custom object array
        Employee[] empArr = new Employee[4];
        empArr[0] = new Employee(10, "Mikey", 25, 10000);
        empArr[1] = new Employee(20, "Arun", 29, 20000);
        empArr[2] = new Employee(5, "Lisa", 35, 5000);
        empArr[3] = new Employee(1, "Pankaj", 32, 50000);
        
        //sorting employees array using Comparable interface implementation
        Arrays.sort(empArr);
        System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Salary
        Arrays.sort(empArr, Employee.SalaryComparator);
        System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Age
        Arrays.sort(empArr, Employee.AgeComparator);
        System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Name
        Arrays.sort(empArr, Employee.NameComparator);
        System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));
        
        //Employees list sorted by ID and then name using Comparator class
        empArr[0] = new Employee(1, "Mikey", 25, 10000);
        Arrays.sort(empArr, new EmployeeComparatorByIdAndName());
        System.out.println("Employees list sorted by ID and Name:\n"+Arrays.toString(empArr));
    }

}

Here is the output of the above program:

这是上面程序的输出:

Default Sorting of Employees list:
[[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 list sorted by Salary:
[[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]]
Employees list sorted by Age:
[[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]]
Employees list sorted by Name:
[[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]]
Employees list sorted by ID and Name:
[[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]]

The java.lang.Comparable and java.util.Comparator are powerful interfaces that can be used to provide sorting objects in java.

java.lang.Comparablejava.util.Comparator是功能强大的接口,可用于在Java中提供排序对象。

可比与比较器 (Comparable vs Comparator)

  1. Comparable interface can be used to provide single way of sorting whereas Comparator interface is used to provide different ways of sorting.

    可比较接口可用于提供单一的排序方式,而比较器接口可用于提供不同的排序方式。
  2. For using Comparable, Class needs to implement it whereas for using Comparator we don’t need to make any change in the class.

    对于使用Comparable,Class需要实现它,而对于使用Comparator,我们不需要在类中进行任何更改。
  3. Comparable interface is in java.lang package whereas Comparator interface is present in java.util package.

    可比接口位于java.lang包中,而比较器接口位于java.util包中。
  4. We don’t need to make any code changes at client side for using Comparable, Arrays.sort() or Collection.sort() methods automatically uses the compareTo() method of the class. For Comparator, client needs to provide the Comparator class to use in compare() method.

    我们不需要在客户端进行任何代码更改即可使用Comparable, Arrays.sort()Collection.sort()方法自动使用该类的compareTo()方法。 对于Comparator,客户端需要提供Comparator类以在compare()方法中使用。

Do you know that Collections.sort() method that takes Comparator argument follows Strategy Pattern?

您是否知道采用Comparator参数的Collections.sort()方法遵循策略模式

GitHub Repository. GitHub存储库中检出完整的代码和更多核心Java示例。

翻译自: https://www.journaldev.com/780/comparable-and-comparator-in-java-example

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值