对象的Java排序数组列表 之 比较器和比较器示例

很多时候,我们需要按字段或字母顺序对对象的数组列表进行排序,尤其是当您在以人为主要实体(例如HR)的域上工作时,您会更经常遇到此要求。有很多方法可以对此类列表进行排序,范围从使用javascript在客户端UI上进行排序使用复杂算法在服务器端对对象的数组列表进行排序,有时甚至在数据库中也可以。

如果您一次没有数百万条记录要排序(最好的数据库查询方式),那么我建议您考虑使用Comparable比较器接口。

目录

1.雇员-模型类
2.比较接口
3.比较器接口
4. Java 8中的比较器
5. SortedSet和SortedMap 
6. hashCode()和equals()

1.员工–模特班

我们的Employee类是普通的老班有四个字段:idfirstNamelastNameage。我故意选择了这些领域。

Employee.java
package corejava.compare;
public class Employee {
    private int id = -1;
    private String firstName = null;
    private String lastName = null;
    private int age = -1;
    public Employee(int id, String fName, String lName, int age) {
        this.id = id;
        this.firstName = fName;
        this.lastName = lName;
        this.age = age;
    }
    // Setters and Getters
    @Override
    public String toString() {
        return "Employee : " + id + " - " + firstName + " - " + lastName
        + " - " + age + "n";
    }
}

2.对象的Java排序数组列表–比较示例

Comparable接口提供了一个方法compareTo(T o)以便在任何类中实现,以便可以比较该类的两个实例。

方法语法为:

public int compareTo(T o);

这里,在要比较的两个实例中,一个是实例本身,将在该实例上调用方法,另一个实例作为参数传递o

让我们Employee看看实现Comparable接口后我们的类的外观。

Employee.java
package corejava.compare;
public class Employee implements Comparable<Employee> {
    private int id = -1;
    private String firstName = null;
    private String lastName = null;
    private int age = -1;
    public Employee(int id, String fName, String lName, int age) {
        this.id = id;
        this.firstName = fName;
        this.lastName = lName;
        this.age = age;
    }
    @Override
    public int compareTo(Employee o) {
        return this.id - o.id;
    }
    // Setters and Getters
    @Override
    public String toString() {
        return "Employee : " + id + " - " + firstName + " - " + lastName + " - " + age + "\n";
    }
}

在我们的例子中,对员工列表进行排序的默认方式是按id。无论如何,您的默认排序顺序是in compare()方法。

在实现的compare()方法中,我们仅返回了两个实例的雇员ID的差。两个相等的员工ID将返回零,表示同一对象。

2.1。Collections.sort()

让我们测试compare()在上述Employee类中实现的方法。

package corejava.compare;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestSorting {
    public static void main(String[] args) {
        Employee e1 = new Employee(1, "aTestName", "dLastName", 34);
        Employee e2 = new Employee(2, "nTestName", "pLastName", 30);
        Employee e3 = new Employee(3, "kTestName", "sLastName", 31);
        Employee e4 = new Employee(4, "dTestName", "zLastName", 25);
        List<Employee> employees = new ArrayList<Employee>();
        employees.add(e2);
        employees.add(e3);
        employees.add(e1);
        employees.add(e4);
        // UnSorted List
        System.out.println(employees);
        Collections.sort(employees);
        // Default Sorting by employee id
        System.out.println(employees);
    }
}

在上述程序中,第一个打印语句打印未排序的员工列表,而在第二个打印语句中,员工按其员工ID排序。

安慰
//Unsorted
[Employee : 2 - nTestName - pLastName - 30
, Employee : 3 - kTestName - sLastName - 31
, Employee : 1 - aTestName - dLastName - 34
, Employee : 4 - dTestName - zLastName - 25]
//Sorted
[Employee : 1 - aTestName - dLastName - 34
, Employee : 2 - nTestName - pLastName - 30
, Employee : 3 - kTestName - sLastName - 31
, Employee : 4 - dTestName - zLastName - 25]

3. Java对象的排序数组列表–比较器示例

因此,现在我们可以按员工对员工列表进行排序id。现在让我们考虑一种情况,其中我们希望根据一些用户输入来对员工列表进行排序,这实际上是对字段进行排序,即有时他想要sort by first name,有时sort by age也想要。

这可以通过jquery插件轻松实现,但是如果浏览器禁用了javascript怎么办。您只需要在服务器端对列表进行排序就不会破坏应用程序功能。

这是Comparator用于拯救您的界面。A Comparator可用于在某些特定基础上对实例集合进行排序。为了排序不同的字段,我们需要多个Comparator实现

3.1。比较器界面示例

我们为不同的排序情况确定了多种实现。让我们写它们。

3.1.1。名分类器
FirstSorter.java
package corejava.compare;
import java.util.Comparator;
public class FirstNameSorter implements Comparator<Employee>{
@Override
public int compare(Employee o1, Employee o2) {
return o1.getFirstName().compareTo(o2.getFirstName());
}
}
3.1.2。姓氏分类器
LastNameSorter.java
package corejava.compare;
import java.util.Comparator;
public class LastNameSorter implements Comparator<Employee> {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.getLastName().compareTo(o2.getLastName());
    }
}
3.1.3。年龄分类器
AgeSorter.java
package corejava.compare;
import java.util.Comparator;
public class AgeSorter implements Comparator<Employee> {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.getAge() - o2.getAge();
    }
}

3.2。如何与比较器比较

因此,从理论上讲,我们应该能够以最少的代码对任意字段进行排序。让我们看看我们是否真的是:

package corejava.compare;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestSorting
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee(1, "aTestName", "dLastName", 34);
        Employee e2 = new Employee(2, "nTestName", "pLastName", 30);
        Employee e3 = new Employee(3, "kTestName", "sLastName", 31);
        Employee e4 = new Employee(4, "dTestName", "zLastName", 25);
        List<Employee> employees = new ArrayList<Employee>();
        employees.add(e2);
        employees.add(e3);
        employees.add(e1);
        employees.add(e4);
        // UnSorted List
        System.out.println(employees);
        Collections.sort(employees);
        // Default Sorting by employee id
        System.out.println(employees);
        Collections.sort(employees, new FirstNameSorter());
        // Sorted by firstName
        System.out.println(employees);
        Collections.sort(employees, new LastNameSorter());
        // Sorted by lastName
        System.out.println(employees);
        Collections.sort(employees, new AgeSorter());
        // Sorted by age
        System.out.println(employees);
    }
}
Output:
//Unsorted
[Employee : 2 - nTestName - pLastName - 30
, Employee : 3 - kTestName - sLastName - 31
, Employee : 1 - aTestName - dLastName - 34
, Employee : 4 - dTestName - zLastName - 25]
//Default sorting based on employee id
[Employee : 1 - aTestName - dLastName - 34
, Employee : 2 - nTestName - pLastName - 30
, Employee : 3 - kTestName - sLastName - 31
, Employee : 4 - dTestName - zLastName - 25]
//Sorted by first name
[Employee : 1 - aTestName - dLastName - 34
, Employee : 4 - dTestName - zLastName - 25
, Employee : 3 - kTestName - sLastName - 31
, Employee : 2 - nTestName - pLastName - 30]
//Sorted by last name
[Employee : 1 - aTestName - dLastName - 34
, Employee : 2 - nTestName - pLastName - 30
, Employee : 3 - kTestName - sLastName - 31
, Employee : 4 - dTestName - zLastName - 25]
//Sorted by age
[Employee : 4 - dTestName - zLastName - 25
, Employee : 2 - nTestName - pLastName - 30
, Employee : 3 - kTestName - sLastName - 31
, Employee : 1 - aTestName - dLastName - 34]

在班级的输出上方可以清楚地看到,现在我们可以使用适当的Comparator实现对任何字段上的员工列表进行排序。

4. Java 8中的比较器

Lambda的最新更改使使用Comparator变得比以往更加容易。

Lambda的比较器
List<Employee> employees  = getEmployeesFromDB();
 
//Sort all employees by first name
employees.sort(Comparator.comparing(e -> e.getFirstName()));
 
//OR you can use below
employees.sort(Comparator.comparing(Employee::getFirstName));
//Sort all employees by first name in reverse order
Comparator<Employee> comparator = Comparator.comparing(e -> e.getFirstName());
employees.sort(comparator.reversed());
//Sorting on multiple fields; Group by.
Comparator<Employee> groupByComparator = Comparator.comparing(Employee::getFirstName).thenComparing(Employee::getLastName);
employees.sort(groupByComparator);

阅读更多:Java 8比较器示例

5.对象的Java排序数组列表– SortedSet和SortedMap

了解这两个接口在代码收集API中的重要性非常重要,这些API 通过属性提供对象的隐式行为排序列表。这样的API例如是SortedMapSortedSet

这些集合按排序顺序存储元素。为了确定排序,他们还使用compare()方法。永远记住,如果Employee类没有实现Comparable接口并且也没有使用接口Comparator,那么在已排序的集合中添加元素将给您error

在SortedSet中添加不可比较的项目
Exception in thread "main" java.lang.ClassCastException: corejava.compare.Employee cannot be cast to java.lang.Comparable
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at corejava.compare.SortedSetTest.main(SortedSetTest.java:17)

因此,有必要使用两个接口中的任何一个来将实例存储在已排序的集合中。

5.1。具有可比较的SortedSet

如果不使用Comparator实现,则将使用Employeeclass的compare()方法进行排序。

SortedSetTest.java
package corejava.compare;
import java.util.SortedSet;
import java.util.TreeSet;
public class SortedSetTest
{
    public static void main(String[] args)
    {
        SortedSet<Employee> set = new TreeSet<Employee>();
        Employee e1 = new Employee(1, "aTestName", "dLastName", 34);
        Employee e2 = new Employee(2, "nTestName", "pLastName", 30);
        Employee e3 = new Employee(3, "kTestName", "sLastName", 31);
        Employee e4 = new Employee(4, "dTestName", "zLastName", 25);
        set.add(e2);
        set.add(e3);
        set.add(e1);
        set.add(e4);
        System.out.println(set);
    }
}

程序输出:

安慰
[Employee : 1 - aTestName - dLastName - 34
, Employee : 2 - nTestName - pLastName - 30
, Employee : 3 - kTestName - sLastName - 31
, Employee : 4 - dTestName - zLastName - 25]

5.1。带比较器的SortedSet

如果要使用Comparator实现添加其他一些排序行为,则可以将Comparatorto 传递给sorted collection的构造函数。例如

SortedSetTest.java
package corejava.compare;
import java.util.SortedSet;
import java.util.TreeSet;
public class SortedSetTest {
    public static void main(String[] args)
    {
        SortedSet<Employee> set = new TreeSet<Employee>(new FirstNameSorter());
        Employee e1 = new Employee(1, "aTestName", "dLastName", 34);
        Employee e2 = new Employee(2, "nTestName", "pLastName", 30);
        Employee e3 = new Employee(3, "kTestName", "sLastName", 31);
        Employee e4 = new Employee(4, "dTestName", "zLastName", 25);
        set.add(e2);
        set.add(e3);
        set.add(e1);
        set.add(e4);
        System.out.println(set);
    }
}

程序输出:

安慰
[Employee : 1 - aTestName - dLastName - 34
, Employee : 2 - nTestName - pLastName - 30
, Employee : 3 - kTestName - sLastName - 31
, Employee : 4 - dTestName - zLastName - 25]

在上面的代码中,Comparator将优先,并将成为默认的排序顺序。很容易,对吧?

6. hashCode()和equals()

如果您在类中重写了equals()方法,请Employee务必记住要遵守其行为。

如果两个对象使用equals()方法相等,则compare()方法应返回“ 0 ”。

我希望在描述如何对对象的数组列表进行排序时足够清晰。如果您仍有疑问,请发表评论。我很乐意解决。

学习愉快!

saigon has written 1440 articles

Leave a Reply