有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java使用多个参数对对象进行排序

我最近一直在努力更好地理解排序算法及其与不同类型输入的关系。目前,我正在开发一个学生管理程序,其中每个学生都有三个参数:姓氏、GPA和用户ID(String、double、int)。它们分别存储在一个学生类中,包含这三个参数,并且有几十个学生(该程序的一个关键功能是输入、删除和更新学生)

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

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


共 (6) 个答案

  1. # 1 楼答案

    在Java中实现这一点的方法是使用不同的Comparators。然后你说:

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

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

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

    例如,名称比较器可能是:

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

    GPA比较程序可能是

    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;
         }
     }
    
  2. # 2 楼答案

    它实际上与排序数字没有什么不同,只是在这种情况下,您的“数字”是用户的三个字段,每个数字的值受每个字段的值的约束,字段的顺序决定排序的顺序

    更具体地说,您有一个包含3个字段的元组:<GPA, Last Name, User ID>,假设您希望按GPA、姓氏和用户ID进行排序

    与219排序在139之上的方式相同(即,即使“十”位更低,“百”位也有更高的值),类似<3.75, Jones, 5>的元组将排序在<3.0, Adams, 2>之上,因为“GPA位”(更重要)有更高的值,即使“姓氏位”更低(例如,琼斯比亚当斯“更低”)

  3. # 3 楼答案

    这可能与主题无关,但是如果您想尝试一些很酷的东西,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
    

    或者使用方法引用,假设绝地有一个类似于比较器的方法(相同的签名)

    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. # 4 楼答案

    我建议在Student类中实现Comparable接口,如下所示

    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);
    
  5. # 5 楼答案

    使用多个比较器

    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
            };
        }
    }
    
  6. # 6 楼答案

    实现这一点的典型方法是对接受^{}的任何类型编写通用排序算法,然后编写不同的Comparator按不同字段排序