Java对具有多个参数的对象进行排序

时间:2012-04-04 17:44:27

标签: java sorting object

我最近一直致力于更好地理解排序算法及其与不同类型输入的关系。目前,我正在开展一项学生管理计划,每个学生都有三个参数:姓氏,GPA和用户ID(String,double,int)。它们各自存储在具有这三个参数的Student类中,并且有DOZENS学生(该程序的一个关键特征是输入,删除和更新学生)。

我的问题是:使用主要排序算法(mergesort,quicksort等),按每个参数排序学生列表的最佳方法是什么?例如,执行mergesort以按GPA对列表进行排序的最佳方法是什么?或者使用quicksort按姓氏对列表进行排序?

基本上我的问题归结为......我可以对这些对象进行排序,如果它们没有三个参数(编写一个mergesort来排序100个数字对我来说非常容易)。如何管理其他两个参数并确保在排序后可以访问它们?

6 个答案:

答案 0 :(得分:5)

在Java中完成此操作的方法是使用不同的Comparators。然后你说:

Collections.sort(list, new NameComparator());

或者

Collections.sort(list, new GpaComparator());

这些比较器使用不同的字段来定义两个元素之间的顺序。

例如,Name Comparator可能是:

class NameComparator implements Comparator< Student> {
    @Override public int compare(Student left, Student right) {
        return left.getName().compareTo(right.getName());
    }
}

GpaComparator可能

class GpaComparator implements Comparator< Student> {
    @Override public int compare(Student left, Student right) {
        if (left.getGpa() < right.getGpa()) {
            return -1;
       } else if (left.getGpa() > right.getGpa()) {
            return 1;
       } else {
           return 0;
     }
 }

答案 1 :(得分:1)

我建议您在Comparable类中实施Student界面,如下所示

public class Student implements Comparable {
   public int compareType; //you can make this an enum if you want
   ...

   public int compareTo(Object o) {
       if(compareType == 0) 
         return gpaCompareTo(o);
       else if(compareType == 1)
         return nameCompareTo(o);

       return idCompateTo(o); 
   }

   public int gpaCompareTo(Object o) {
       //implement your gpaCompareTo
   }

   public int nameCompareTo(Object o) {
       //implement your nameCompareTo
   }

   public int idCompareTo(Object o) {
       //implement your idCompareTo
   }
}

然后使用像

这样的内置排序
List<Student> list = new ArrayList<Student>();
...
Collections.sort(list);

或者你无法实现Comparable并设计自己的比较器

public class MyComparator implements Comparator<Student> {

   public int compare(Student o1, Student o2) {
      //implement the comparator
   }

   public boolean equals(Object o) {
      //implement the equals 
   }
}

然后您可以使用其他Collection's排序方法

Collections.sort(list, MyComparator);

答案 2 :(得分:1)

执行此操作的典型方法是在接受Comparator的任何类型上编写通用排序算法,然后编写不同的Comparator以按不同字段排序。

答案 3 :(得分:1)

这可能是偏离主题的,但如果你想尝试一些很酷的东西,JDK 8 Lambda Preview提供了一些使用Lamda expressions and method references来定义比较器的很酷的方法。

我们说我们有一个班级:

class Jedi  {
   private final String name;
   private final int age;
   //...
}

然后是他们的集合:

List<Jedi> jediAcademy = asList(new Jedi("Obiwan",80), new Jedi("Anakin", 30));
sort(jediAcademy, (j1, j2) -> j1.getAge() > j2.getAge() ? 1 : j1.getAge() < j2.getAge() ? -1 : 0);
System.out.println(jediAcademy); //Anakin, Obiwan

或者使用方法引用,假设Jedi具有表现为比较器(相同签名)的方法

class Jedi  {
  public static int compareByAge(Jedi first, Jedi second){
     return first.age > second.age ? 1 : first.age < second.age ? -1 : 0;
  }
   //...
}

可以使用以下方法通过使用方法引用来生成比较器:

List<Jedi> jediAcademy = asList(new Jedi("Obiwan",80), new Jedi("Anakin", 30));
sort(jediAcademy, Jedi::compareByAge);
System.out.println(jediAcademy);//Anakin, Obiwan

答案 4 :(得分:0)

与排序数字没有什么不同,除了在这种情况下你的&#34;数字&#34;用户的三个字段,每个数字的值受每个字段的值约束,字段的顺序决定了排序排名。

更具体一点,你有一个包含3个字段的Tupple:<GPA, Last Name, User ID>,并假设您要按GPA排序,然后按姓氏和用户ID排序。

与219在139以上排序的方式相同(即&#34;数百&#34;数字具有更高的值,即使&#34;数字&#34;数字更低),类似于{ {1}}将排在<3.75, Jones, 5>之上,因为&#34; GPA数字&#34; (更重要的是)具有更高的价值,即使&#34;姓氏数字&#34;较低(例如琼斯比亚当斯低#34;)

答案 5 :(得分:0)

使用多个比较器

class Student
{

        String lastName;
        dounle GPA;
        int userId


    static Comparator<Student> getStudentLastNameComparator() {
        return new Comparator<Student>() {

            @Override
            public int compare(Student Student1, Student Student2) {
                return Student1.getlastName().compareTo(Student2.getlastName());
            }
            // compare using Student lastName
        };
    }

    static Comparator<Student> getStudentGPAComparator() {
        return new Comparator<Student>() {

            @Override
            public int compare(Student Student1, Student Student2) {
                if(Student1.GPA < Student2.GPA)
                    return 1;
                else
                    return -1;
            }
            // compare using Student GPA
        };
    }

    static Comparator<Student> getStudentUserIdComparator() {
        return new Comparator<Student>() {

            @Override
            public int compare(Student Student1, Student Student2) {
                if(Student1.userId < Student2.userId)
                    return 1;
                else
                    return -1;
            }
            // compare using Student userId
        };
    }
}