在Java中,如何快速排序对象的ArrayList,其中排序字段是多层深度?

时间:2010-10-14 17:28:23

标签: java arrays sorting arraylist quicksort

基本上,我有一个名为“Employees”的Container类,其中包含一个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”对象基于String对象“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 个答案:

答案 0 :(得分: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());
  }
  ...
}

答案 1 :(得分:4)

定义Employee implements Comparable<Employee>

compareTo方法中,深入了解图层并比较所需的字符串。然后您可以使用Collections.sort(),也可以将数据存储在SortedSet中,这是自然订购的。

答案 2 :(得分: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

答案 3 :(得分:2)

彼得·德威斯和其他人给了你非常好的答案。你可以使用

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

使用您定义的Comparator对myList进行排序。 &lt; ===那是什么意思?

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

但是,如果要对对象进行排序,首先必须定义一个顺序。由于对象可以具有各种属性,因此我可能希望按照耳朵大小对员工进行排序。在这种情况下,我只是告诉Java我的类实现了Comparable。使用泛型,我必须指定它实现Comparable&lt;员工&gt;因为我正在为我的员工对象(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定义了元素的顺序。

来自可比较&lt; T&GT;规格:

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); 

关键字将引用 x

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

我们还可以查看一个String示例:

这意味着如果我想让“梅德韦杰夫”来到“普京”之前(因为“M”在英文字母中的'P'之前出现),我必须声明我希望compareTo在比较Medvedev时返回-1普京。

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

然后是行

TheMString.compareTo(ThePString);

将评估为-1。

现在,像Collections.sort( list ,比较器)这样的标准例程将能够使用compareTo返回的这些值来确定列表的顺序。您可能知道,排序是一种基于比较的操作,我们需要知道什么值是“小于”或“大于”另一个值才能进行有意义的排序。

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

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

我希望有所帮助。