4

基本上,我有一个名为“Employees”的容器类,其中包含一个 ArrayList。此 ArrayList 包含“Employee”对象,这些对象又包含“EmployeeData”对象,后者又包含 String 对象,例如“first”或“last”(它们是员工姓名)。

这是 ArrayList 结构的示意图:

ArrayList[Employee] emps ==> 1:Many ==> Employee emp
Employee emp ==> 1:1 ==> EmployeeData data
EmployeeData data ==> 1:2 ==> String last // A string that contains employee's last name.

我到底如何对 ArrayList 执行快速排序,以便其中的“Employee”对象根据字符串对象“last”按字母顺序排列?好像有点复杂!


这是我的课程的基本设计:

class Employees{
    //data:
        private ArrayList<Employee> emps = new ArrayList<Employee>();

    //Some constructors go here

    //Methods to add, remove, toString, etc, go here

    public /*output a sorted ArrayList?*/ sort(){
        // Some kind of "quicksort" in here to modify or create a new ArrayList sorted by employee's las name...
    }
}

class Employee{
    //data:
    EmployeeData data;
    // Some methods to construct and modify EmployeeData data.
}

class EmployeeData{
    //data:
        String first, last; // I wish to sort with "last". How do you do it?
        double payrate, hours;
    //...methods...
}

如您所见,这些是类。我不知道如何在“Employees”类中实现“sort”,以便通过“EmployeeData”类的“last”变量对 ArrayList 进行排序。

4

4 回答 4

11

您可以制作一个比较器,例如:

public class MyComparator implements Comparator<Employee>
{
  public int compare(Employee e1, Employee e2)
  {
    return e1.getData().getLast().compareTo(e2.getData().getLast());
  }
}

然后使用它对列表进行排序。

Collections.sort(myList, new MyComparator());

或者,您可以使用 TreeSet 使用此比较器对插入进行排序,或者使 Employee 成为可比较的对象,以便使用 Collections 或 SortedSet 进行排序。

public class Employee implements Comperable<Employee>
{
  ...
  public int compareTo(Employee e)
  {
    return this.getData().getLast().compareTo(e.getData().getLast());
  }
  ...
}
于 2010-10-14T17:38:28.970 回答
4

定义Employee implements Comparable<Employee>.

在该compareTo方法中,深入研究层并比较您需要的字符串。然后可以使用Collections.sort(),也可以将数据存储在SortedSet自然有序的 a 中。

于 2010-10-14T17:30:00.147 回答
3

最佳实践是将排序逻辑封装在存储在 ArrayList 中的类中,本例中为 Employee。通过创建 compareTo(Employee) 方法来实现 Comparable。

import java.util.*;

public class Employee  implements Comparable<Employee> {
    public EmployeeData Data;

    public Employee(String first, String last)
    {
        Data = new EmployeeData(first, last);
    }

    public int compareTo(Employee other)
    {
        return Data.Last.compareTo(other.Data.Last);
    }

    public String toString() {
        return Data.First + " " + Data.Last;
    }

    public static void main(String[] args) throws java.io.IOException {
        ArrayList list = new ArrayList();
        list.add(new Employee("Andy", "Smith"));
        list.add(new Employee("John", "Williams"));
        list.add(new Employee("Bob", "Jones"));
        list.add(new Employee("Abraham", "Abrams"));
        Collections.sort(list);
        for (int i = 0; i < list.size(); i++)
        {
            System.out.println(list.get(i));
        }
        System.in.read();
    }
}

public class EmployeeData {
    public String First;
    public String Last;
    public EmployeeData(String first, String last)
    {
        First = first;
        Last = last;
    }
}

输出:

Abraham Abrams
Bob Jones
Andy Smith
John Williams
于 2010-10-14T18:05:33.397 回答
2

Peter DeWeese 和其他人已经给了你很好的答案。您可以使用

Collections.sort(myList, new MyComparator());

使用您定义的 Comparator 对 myList 进行排序。<=== 这到底是什么意思?

在 Java 中,如果某些东西实现了 Comparable (java.lang.comparable),那么您可以为您的元素定义一个顺序。您似乎知道Java 泛型是什么,因为您使用它们将 ArrayList 声明为 < Employee > 类型。这很棒,因为您可以将一个 Employee 对象存储到 ArrayList 的每个条目中。到现在为止还挺好?

但是,如果要对对象进行排序,首先必须定义一个顺序。由于对象可以具有各种属性,也许我想按耳朵大小对员工进行排序。在这种情况下,我只是告诉 Java 我的类实现了 Comparable。对于泛型,我必须指定它实现 Comparable< Employee >,因为我正在为我的 Employee 对象(peons、minions 等)定义一个顺序。

Peter DeWeese 提到:

 public int compareTo(Employee e)
 {
     return this.getData().getLast().compareTo(e.getData().getLast());
 }

Jason Goemaat 提到:

public int compareTo(Employee other)
{
    return Data.Last.compareTo(other.Data.Last);
}

这到底是什么意思?如果我说我的类实现了 Comparable,那么我需要定义一个 compareTo 函数。(接口是需要实现的方法的集合)函数 compareTo 定义了我的元素的顺序。

来自 Comparable< T> 规范:

int compareTo(T o)

将此对象与指定对象进行比较以进行排序。返回负整数、零或正整数,因为此对象小于、等于或大于指定对象。

如果我要比较耳朵的大小,假设我希望大耳朵在我的列表中排在第一位,那么我可以(重新)将 compareTo 定义为:

public int compareTo(Employee e)
{
    if (this.earSize > e.earSize) //big ears come first
        return -1;
    if (this.earSize == e.earSize) //equality
        return 0;
    else
        return 1; // if e.earSize > this.earSize then return 1
}

为了回答 Steve Kuo 的问题,我们将关键字this放在比较器中,因为当我们调用 compareTo 方法时

x.compareTo(y); 

关键字this将引用x

您可以将 compareTo 视为对象x的方法,因此当您调用 x.compareTo(y) 时,您实际上是在对象x的范围内说 this.compareTo(y) 。

我们还可以看一个字符串示例:

这意味着,如果我希望“Medvedev”出现在“Putin”之前(因为在英文字母表中,“M”出现在“P”之前)我必须声明在将 Medvedev 与普京进行比较时,我希望 compareTo 返回 -1。

String TheMString = "Medvedev";
String ThePString = "Putin";

然后这条线

TheMString.compareTo(ThePString);

将评估为-1。

现在,诸如 Collections.sort( list ,comparator) 之类的标准例程将能够使用 compareTo 返回的这些值来计算list的 [absolute] 顺序。您可能知道,排序是基于比较的操作,我们需要知道什么值“小于”或“大于”另一个值才能进行有意义的排序。

一个重要的警告是,如果你在字符串上调用 compareTo,它默认按字母顺序,所以你可以简单地告诉 compareTo 返回 A.compareto(B),它会确保字符串是有序的。

通常(好吧,我应该说,在其他情况下)重新定义 compareTo 方法时,您必须显式声明一个 neg/zero/pos 返回值。

我希望这会有所帮助。

于 2010-10-14T19:04:45.847 回答