Java sorting objects with multiple parameters

I recently worked on improving my understanding of sorting algorithms and their relationship to different input types. I am currently working on a student management program where each student has three parameters: Last Name, VGU and User ID (String, double, int). Each of them is stored in the Student class with these three parameters, and there are DOSE of students (the key feature of the program is to enter, delete and update students).

My question is, using basic sorting algorithms (mergesort, quicksort, etc.) what is the best way to sort my list of students by each parameter? For example, what is the best way to perform a join to sort the list by GPA? Or use quicksort to sort the list by last name?

Basically my question boils down to ... I can sort these objects if they didn't have three parameters (it's very easy for me to write a merge to sort 100 numbers). How do I manage the other two parameters and make sure they are available after sorting?

+3


source to share


6 answers


As it is done in Java, you need to use different Comparators . Then you say:

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

      

or

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

      

These comparators use different fields to determine the order between two elements.



For example, a Name Comparator could be:

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

      

And the GpaComparator can be

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

      

+5


source


I would recommend to implement the interface Comparable

in your Student

class like this

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

      

And then use an inline view like

List<Student> list = new ArrayList<Student>();
...
Collections.sort(list);

      



Or you cannot implement Comparable

and create your own comparators

public class MyComparator implements Comparator<Student> {

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

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

      

Then you can use another sorting method Collection's

Collections.sort(list, MyComparator);

      

+1


source


The typical way to do this is to write a general sorting algorithm for any type that accepts Comparator

, and then write different ones Comparator

to sort on different fields.

+1


source


This is probably off-topic, but if you want to try something cool, the JDK 8 Lambda Preview offers some cool ways to define comparators using Lamda expressions and method references .

Let's say we have a class:

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

      

And then a set of them:

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

      

Or with method references if Jedi has a method that behaves like a comparator (same signature)

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

      

Which can be used as follows to create a comparator using a method reference:

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

      

+1


source


This is really nothing more than a sorting of numbers, except that in this case your "numbers" are your users' three fields, the meaning of each digit is limited to the values ​​of each field, and the order of the fields is determined by the sort.

To be more specific, you have a Tupple with three fields: <GPA, Last Name, User ID>

and lets assume you want to sort by GPA and then by Last Name and User ID.

In the same way that 219 is sorted above 139 (i.e. the "hundreds" digit is higher, even if the "tens" is lower), a scoreboard like this <3.75, Jones, 5>

will be sorted higher <3.0, Adams, 2>

because the "GPA" digit (which is more significant ) has a higher value even if the "family number" is lower (for example, Jones is "lower" than Adams).

0


source


Use multiple comparators

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

      

0


source







All Articles