【问题标题】:Java Comparator Multiple field sort not workingJava比较器多字段排序不起作用
【发布时间】:2016-03-25 21:03:17
【问题描述】:

我正在尝试按姓氏降序排序,然后是等级,并且一直在关注这个example

我只是通过姓氏排序而不是等级排序。我没有得到什么?

@Override
public int compare(Student o1, Student o2) {
    int c;
    c = o1.getLastName().compareToIgnoreCase(o2.getLastName());
    if (c == 0) {
        c = Double.compare(o1.getGrade(), o2.getGrade());
    }
    return c;
}

我并没有完全理解上面提到的例子在 c == 0 方面是如何工作的,因为 c 在排序时永远不会等于零。这让我明白了为什么成绩没有排序,但这并没有把我带到我需要的地方。

排序在这里执行:

@Override
public void execute(List<Student> list) {
    LastNameComparator cmp = new LastNameComparator(studentList);
    Collections.sort(studentList, cmp);

}

而测试类是这样的:

public static void main(String[] args) {
    // TODO code application logic here

    for (int i = 0; i < 20; i++) {
        Student student = new Student(randomInteger(1,50), NameGenerator.generateName(), NameGenerator.generateName(), Math.round(Math.random()*10.0)/10.0);
        studentList.add(student);
    }
    System.out.println("--Unsorted--");

    for (Student student : studentList) {
        System.out.println(student.getStudentID());
        System.out.println(student.getFirstName());
        System.out.println(student.getLastName());
        System.out.println(student.getGrade());
    }

    Command sortLastName = new LastNameComparator(studentList);
    sortLastName.execute(studentList);

    System.out.println("--Sorted--");


    for (Student student : studentList) {
        System.out.println(student.getStudentID());
        System.out.println(student.getFirstName());
        System.out.println(student.getLastName());
        System.out.println(student.getGrade());
    }
}

名称是这样生成的。我从here得到它:

public class NameGenerator {
    private static String[] Beginning = { "Kr", "Ca", "Ra", "Mrok", "Cru",
         "Ray", "Bre", "Zed", "Drak", "Mor", "Jag", "Mer", "Jar", "Mjol",
         "Zork", "Mad", "Cry", "Zur", "Creo", "Azak", "Azur", "Rei", "Cro",
         "Mar", "Luk" };
   private static String[] Middle = { "air", "ir", "mi", "sor", "mee", "clo",
         "red", "cra", "ark", "arc", "miri", "lori", "cres", "mur", "zer",
         "marac", "zoir", "slamar", "salmar", "urak" };
   private static String[] End = { "d", "ed", "ark", "arc", "es", "er", "der",
         "tron", "med", "ure", "zur", "cred", "mur" };

   private static Random rand = new Random();

   public static String generateName() {

      return Beginning[rand.nextInt(Beginning.length)] + 
            Middle[rand.nextInt(Middle.length)]+
            End[rand.nextInt(End.length)];

   }
} 

更新 我知道这只有在名称相同的情况下才有效。这是对我不起作用的地方,因为随机名称生成器很少有机会生成两次相同的名称。我正在研究如何让列表按姓氏按降序排序,然后按等级排序,无论名称是否相同。如果名字相同,则等级高。

【问题讨论】:

  • c 应该等于 0 如果姓氏相同。因此,如果您有多个姓氏为“Smith”的人,那么“Smith's”将根据等级进行排序。您提供的代码应该可以做到这一点。
  • 您的代码非常混乱。 execute 方法对传递给它的列表进行排序。
  • 为什么你的参数的构造函数要带参数?这没有多大意义......
  • 如何生成名称?你能提供样本输入和输出吗?为了检查这是否如您所愿,您需要添加几个同名的人;如果所有人都有不同的名字,那么确实c == 0 永远不会是true,并且不会应用第二个排序标准。
  • @Mike C 好的,我明白了——所以如果我的名单上没有任何人的姓氏相同,那么这段代码除了对姓氏进行排序之外什么都不做?跨度>

标签: java sorting


【解决方案1】:

考虑如下学生类

public class Student implements Comparable<Student> {
    String name;
    int id;
    double gpa;

    public Student(String name, int id, double gpa) {
        this.name = name;
        this.id = id;
        this.gpa = gpa;
    }

    @Override
    public int compareTo(Student o2) {
        int c;
        c = this.name.compareToIgnoreCase(o2.name);
        if (c == 0) {
            c = Double.compare(this.gpa, o2.gpa);
        }
        return c;
    }

}

那么下面的main函数给出正确的输出

public static void main(String[] args) {

ArrayList<Student> studentList = new ArrayList<Student>();
studentList.add(new Student("Milind", 1, 7.73));
studentList.add(new Student("Milind", 1, 7.70));
studentList.add(new Student("Mike", 1, 7.80));
System.out.println("--Unsorted--");

for (Student student : studentList) {
    System.out.print(student.name + ": ");
    System.out.print(student.gpa);
    System.out.println();
}
System.out.println();

Collections.sort(studentList);
System.out.println("--Sorted--");

for (Student student : studentList) {
    System.out.print(student.name + ": ");
    System.out.print(student.gpa);
    System.out.println();
}

}

输出:

--Unsorted--
Milind: 7.73
Milind: 7.7
Mike: 7.5

--Sorted--
Mike: 7.8
Milind: 7.7
Milind: 7.73

Mike 首先出现,因为它是按字母顺序排列的。并且名字 Milind 与接下来的 2 相同,因此根据 GPA 排序。

应用相同的逻辑,您还将获得基于多个字段的输出。在这种情况下,当 Firstname 相同时 GPA。

【讨论】:

  • 但是,如果所有三个学生的姓氏都不同,这不会按年级排序,对吧?如此处所示,成绩最高的迈克先来,然后是成绩较低的米林德。
  • 比较器仅用于检查名字。所以是的,如果所有 3 名学生的姓氏不同或相同,那没关系,只有名字相同时,输出才会按 GPA 排序。基本上排序将仅按名字进行,如果名字相同,则按 GPA。姓氏可能相同,也可能不一样。 [这是根据我在上面的学生类中编写的比较器]
  • 我正在寻找一种按姓氏和 gpa 排序的解决方案,无论名称是否相同。在您的示例中,它将是 Mike 7.8、Milind、7.73、Milind 7.7。此代码与我提到的示例相同,但还没有到达我需要的地方。
  • 那么你必须改变Student类。在你的学生课上是这样的:@Override public int compareTo(Student o2) { int c; c = this.lastname.compareToIgnoreCase(o2.lastname); if (c == 0) { c = Double.compare(this.gpa, o2.gpa); } 返回 c; }
  • 我在回答中粘贴的是基本思想。
猜你喜欢
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 2019-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多