1

I'm trying to sort by last name in descending order, then grade, and have been following this example.

I am only getting through the last name sort however and not the grade sort. What am I not getting?

@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;
}

I'm not totally getting how the mentioned example works in terms of c == 0, as c never equals zero while it's sorting. This makes me understand why the grades aren't sorting, but this doesn't get me where I need.

The sort is executed here :

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

}

And the testing class is like this:

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

The names are generated like this. I got it from 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)];

   }
} 

UPDATE I'm understanding that this will only work if the names are the same. This is where this isn't working for me, as the random name generator has a slim chance of generating the same name twice. I am looking into how I can get the list sorted by last name in descending order, then by grade, whether or not the names are the same. If the names are the same, higher grade comes first.

Community
  • 1
  • 1
user25976
  • 1,005
  • 4
  • 18
  • 39
  • 2
    `c` should be equal to `0` if the last names are ever the same. So if you have multiple people with the last name "Smith" then the "Smith's" will be sorted based on grade. The code you've presented should do that. – Mike Cluck Mar 25 '16 at 21:08
  • Your code is very confusing. The execute method sorts a different list from the one passed to it. – Paul Boddington Mar 25 '16 at 21:09
  • Why does your parameter's constructor take a parameter? That doesn't make much sense... – fabian Mar 25 '16 at 21:11
  • How do you generate the names? Can you provide sample input and output? In order to check if this works as you intended, you need to add several people with the same names; if all the people have different names then indeed `c == 0` will never be `true` and the second sorting criterion will not be applied. – Filkolev Mar 25 '16 at 21:11
  • 1
    @Mike C Okay, I see--so if I don't have any people on the list with the same last name, this code won't do anything but sort the last names? – user25976 Mar 25 '16 at 21:12

1 Answers1

0

Consider Student class as below

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

}

Then the main function below gives correct output

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

}

OUTPUT:

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

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

Mike appears first since it is according to alphabetical order. And First name Milind is same for next 2, hence sorted according to GPA.

Applying same logic, you will also get your output based on multiple fields. in this case GPA when Firstname is same.

Milind Gokhale
  • 575
  • 2
  • 14
  • If all three students have different last names, however, this won't get sorted by grade, right? As seen here, Mike with the highest grade comes first, then Milind with a lower grade comes. – user25976 Mar 25 '16 at 21:23
  • The comparator has been written only to check the first name. So yes, If all 3 students have difference last names or same last names, it won't matter and the output will be sorted by GPA only if the first names are same. Basically sorting will happen by FirstName only and if first name is same, then by GPA. Last name may be same or not it won't matter. [This is As per the comparator I've written in Student class above] – Milind Gokhale Mar 25 '16 at 21:25
  • I'm looking for a solution that will sort by last name and gpa, whether or not the names are the same. In your example, it would go Mike 7.8, Milind, 7.73, Milind 7.7. This code is the same as the example I mentioned and doesn't get me where i need yet. – user25976 Mar 25 '16 at 21:27
  • Then you have to change the Student class. something like this in your Student class: @Override public int compareTo(Student o2) { int c; c = this.lastname.compareToIgnoreCase(o2.lastname); if (c == 0) { c = Double.compare(this.gpa, o2.gpa); } return c; } – Milind Gokhale Mar 25 '16 at 21:28
  • What I've pasted in my answer is the basic idea. – Milind Gokhale Mar 25 '16 at 21:28