Issue
I have a list of Student(name, result, rollNo) objects.
List.of(
new Student("Sam", "Pass", "100"),
new Student("Gill", "Not available", "101"),
new Student("Joe", "Fail", "111"),
new Student("Matt", "Fail", "115"),
new Student("Ann", "Pass", "121"),
new Student("Moss", "Pass", "133"),
);
I need to sort the above list as per the below requirements(I am using Java 11)
- Sort the list in the order of the result of students in the order "Fail", "Pass", "Not available"(Not in alphabetical order) Students with results fail should come at the top of the list. Then "pass" and then "Not available"
- If multiple students have the same result, then sort in the ascending order of rollNo.
The end result should be as shown below.
{"Joe", "Fail", "111"}
{"Matt", "Fail", "115"}
{"Sam", "Pass", "100"}
{"Ann", "Pass", "121"}
{"Moss", "Pass", "133"}
{"Gill", "Not available", "101"}
Solution
Since Java 8 we can do Sorting stream on multiple fields
When you want to sort by priority "Fail", "Pass", "Not available", one alternative is to add an extra field in students. This will help to decide the priority of the sorting when there is no natural order. In this example student are ordered by "Pass", "Fail", "Not available" and then sorted by name, just to show some more options.
Sorting code snippet:
Comparator<Student> compareByPriorityThenName =
Comparator.comparing(Student::getPriority)
.thenComparing(Student::getName);
List<Student> sortedStudents = students.stream()
.sorted(compareByPriorityThenName)
.collect(Collectors.toList());
Code Snippet in context:
public static void main(String []args){
List<Student> students = List.of(
new Student("Sam", "Pass", "100"),
new Student("Gill", "Not available", "101"),
new Student("Joe", "Fail", "111"),
new Student("Matt", "Fail", "115"),
new Student("Ann", "Pass", "121"),
new Student("Moss", "Pass", "133")
);
Comparator<Student> compareByPriorityThenName =
Comparator.comparing(Student::getPriority)
.thenComparing(Student::getName);
List<Student> sortedStudents = students.stream()
.sorted(compareByPriorityThenName)
.collect(Collectors.toList());
sortedStudents.forEach(System.out::println);
}
Output:
Student{name='Ann', result='Pass', rollNo='121', priority='1'}
Student{name='Moss', result='Pass', rollNo='133', priority='1'}
Student{name='Sam', result='Pass', rollNo='100', priority='1'}
Student{name='Joe', result='Fail', rollNo='111', priority='2'}
Student{name='Matt', result='Fail', rollNo='115', priority='2'}
Student{name='Gill', result='Not available', rollNo='101', priority='3'}
Added field in Student:
private int priority;
Added methods for sorting priority in class Student:
public int getPriority() {
setPriority();
return priority;
}
private int setPriority() {
if(priority > 0) {
return priority;
}
switch(result) {
case "Pass":
priority = 1;
break;
case "Fail":
priority = 2;
break;
default:
priority = 3;
}
return priority;
}
Method getPriority() in context:
public class Student {
private final String name;
private final String result;
private final String rollNo;
private int priority;
public Student(String name, String result, String rollNo) {
this.name = name;
this.result = result;
this.rollNo = rollNo;
this.priority = 0;
}
public String getName() {
return name;
}
public String getResult() {
return result;
}
public String getRollNo() {
return rollNo;
}
public int getPriority() {
setPriority();
return priority;
}
private int setPriority() {
if(priority > 0) {
return priority;
}
switch(result) {
case "Pass":
priority = 1;
break;
case "Fail":
priority = 2;
break;
default:
priority = 3;
}
return priority;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", result='" + result + '\'' +
", rollNo='" + rollNo + '\'' +
", priority='" + priority + '\'' +
'}';
}
}
Answered By - DigitShifter
Answer Checked By - Willingham (JavaFixing Volunteer)