Java比较器多字段排序不起作用
Posted
技术标签:
【中文标题】Java比较器多字段排序不起作用【英文标题】:Java Comparator Multiple field sort not working 【发布时间】: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 好的,我明白了——所以如果我的名单上没有任何人的姓氏相同,那么这段代码除了对姓氏进行排序之外什么都不做?跨度>
【参考方案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; 我在回答中粘贴的是基本思想。以上是关于Java比较器多字段排序不起作用的主要内容,如果未能解决你的问题,请参考以下文章
mysql中order by 排序用asc和desc不起作用怎么回事