Tuesday

Sort multiple variables with Java 8 stream

I'll try to sort my data as following rules using java 8 stream.
Student.Address.CountryName = B or C is previous  >>
    then Student.StudentDetail.StudentScore descending (nulls  appear at the end) >>
       then Student.StudentDetail.RegistrationTime ascending

Example data:

The following code snippet makes sorting: 
 studentList.stream().sorted(
               Comparator.comparing((Student s)-> !Arrays.stream(priorityCountryName).anyMatch(s.address.getCountryName()::equals))
               .thenComparing(Comparator.comparing(s-> s.studentDetail.getStudentScore(), Comparator.nullsLast(Comparator.reverseOrder())))
               .thenComparing((s1) -> s1.studentDetail.getRegistrationTime())
)

Full example:
import java.io.Serializable;

public class Student implements Serializable {
    
    public final Address address;
    public final StudentDetail studentDetail;
    
    public Student(Address address, StudentDetail studentDetail) {
        this.address = address;
        this.studentDetail = studentDetail;
    }
}
import java.io.Serializable;

public class Address implements Serializable {
    
    private String countryName;
    
    public Address() {
    }

    public String getCountryName() {
        return countryName;
    }

    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }

}
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;

public class StudentDetail implements Serializable {

    private int studentNumber;
    private BigDecimal studentScore;
    private Timestamp registrationTime;
    
    public StudentDetail(){
    }

    public BigDecimal getStudentScore() {
        return studentScore;
    }

    public void setStudentScore(BigDecimal studentScore) {
        this.studentScore = studentScore;
    }

    public Timestamp getRegistrationTime() {
        return registrationTime;
    }

    public void setRegistrationTime(Timestamp registrationTime) {
        this.registrationTime = registrationTime;
    }

    public int getStudentNumber() {
        return studentNumber;
    }

    public void setStudentNumber(int studentNumber) {
        this.studentNumber = studentNumber;
    }
    
}
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class Test {

    public static void main(String[] args) {
       String[] priorityCountryName = {"B", "C"};
 
       List<Student> studentList = addStudents();
       logStudentList("********studentList mix order**********", studentList);

       List<Student> orderedStudentList = studentList.stream().sorted(
               Comparator.comparing((Student s)-> !Arrays.stream(priorityCountryName).anyMatch(s.address.getCountryName()::equals))
               .thenComparing(Comparator.comparing(s-> s.studentDetail.getStudentScore(), Comparator.nullsLast(Comparator.reverseOrder())))
               .thenComparing((s1) -> s1.studentDetail.getRegistrationTime())
           ).collect(Collectors.toList());;
 
       logStudentList("********studentList ordered**********", orderedStudentList);
    }
    
    
    private static List<Student> addStudents() {
       List<Student> studentList = new ArrayList<Student>();
 
       Student student8 = new Student(new Address(), new StudentDetail());
       student8.address.setCountryName("D");
       student8.studentDetail.setStudentScore(new BigDecimal(5.0).setScale(2, BigDecimal.ROUND_HALF_EVEN));
       student8.studentDetail.setRegistrationTime(Timestamp.valueOf("2024-12-31 09:30:00"));
       student8.studentDetail.setStudentNumber(8);
       studentList.add(student8);
 
       Student student3 = new Student(new Address(), new StudentDetail());
       student3.address.setCountryName("B");
       student3.studentDetail.setStudentScore(new BigDecimal(0.1).setScale(2, BigDecimal.ROUND_HALF_EVEN));
       student3.studentDetail.setRegistrationTime(Timestamp.valueOf("2019-12-31 09:30:00"));
       student3.studentDetail.setStudentNumber(3);
       studentList.add(student3);
 
       Student student5 = new Student(new Address(), new StudentDetail());
       student5.address.setCountryName("B");
       student5.studentDetail.setStudentScore(null);
       student5.studentDetail.setRegistrationTime(Timestamp.valueOf("2018-12-31 09:30:00"));
       student5.studentDetail.setStudentNumber(5);
       studentList.add(student5);
 
       Student student2 = new Student(new Address(), new StudentDetail());
       student2.address.setCountryName("C");
       student2.studentDetail.setStudentScore(new BigDecimal(2.0).setScale(2, BigDecimal.ROUND_HALF_EVEN));
       student2.studentDetail.setRegistrationTime(Timestamp.valueOf("2021-12-31 09:30:00"));
       student2.studentDetail.setStudentNumber(2);
       studentList.add(student2);
 
       Student student7 = new Student(new Address(), new StudentDetail());
       student7.address.setCountryName("D");
       student7.studentDetail.setStudentScore(new BigDecimal(5.0).setScale(2, BigDecimal.ROUND_HALF_EVEN));
       student7.studentDetail.setRegistrationTime(Timestamp.valueOf("2023-12-31 09:30:00"));
       student7.studentDetail.setStudentNumber(7);
       studentList.add(student7);
 
       Student student4 = new Student(new Address(), new StudentDetail());
       student4.address.setCountryName("B");
       student4.studentDetail.setStudentScore(new BigDecimal(0.1).setScale(2, BigDecimal.ROUND_HALF_EVEN));
       student4.studentDetail.setRegistrationTime(Timestamp.valueOf("2020-12-31 09:30:00"));
       student4.studentDetail.setStudentNumber(4);
       studentList.add(student4);
 
       Student student9 = new Student(new Address(), new StudentDetail());
       student9.address.setCountryName("D");
       student9.studentDetail.setStudentScore(new BigDecimal(4.0).setScale(2, BigDecimal.ROUND_HALF_EVEN));
       student9.studentDetail.setRegistrationTime(Timestamp.valueOf("2025-12-31 09:30:00"));
       student9.studentDetail.setStudentNumber(9);
       studentList.add(student9);
 
       Student student1 = new Student(new Address(), new StudentDetail());
       student1.address.setCountryName("B");
       student1.studentDetail.setStudentScore(new BigDecimal(6.0).setScale(2, BigDecimal.ROUND_HALF_EVEN));
       student1.studentDetail.setRegistrationTime(Timestamp.valueOf("2022-12-31 09:30:00"));
       student1.studentDetail.setStudentNumber(1);
       studentList.add(student1);
 
       Student student10 = new Student(new Address(), new StudentDetail());
       student10.address.setCountryName("D");
       student10.studentDetail.setStudentScore(null);
       student10.studentDetail.setRegistrationTime(Timestamp.valueOf("2018-11-12 09:30:00"));
       student10.studentDetail.setStudentNumber(10);
       studentList.add(student10);
 
       Student student6 = new Student(new Address(), new StudentDetail());
       student6.address.setCountryName("E");
       student6.studentDetail.setStudentScore(new BigDecimal(5.0).setScale(2, BigDecimal.ROUND_HALF_EVEN));
       student6.studentDetail.setRegistrationTime(Timestamp.valueOf("2023-12-01 09:30:00"));
       student6.studentDetail.setStudentNumber(6);
       studentList.add(student6);
 
       return studentList;
    }
    
    private static void logStudentList(String firstMessage, List<Student> studentList) {
       System.out.println(firstMessage);
 
       for(Student student : studentList) {
          StringBuilder studentBuilder = new StringBuilder();
        
          studentBuilder.append("countryname: ");
          studentBuilder.append(student.address.getCountryName());
          studentBuilder.append(" studentNumber: ");
          studentBuilder.append(student.studentDetail.getStudentNumber());
          studentBuilder.append(" studentScore: ");
          studentBuilder.append(student.studentDetail.getStudentScore());
          studentBuilder.append(" registrationTime: ");
          studentBuilder.append(student.studentDetail.getRegistrationTime());
        
          System.out.println(studentBuilder.toString());
       }
    }

}

//CONSOLE OUTPUT:
********studentList mix order**********
countryname: D studentNumber: 8 studentScore: 5.00 registrationTime: 2024-12-31 09:30:00.0
countryname: B studentNumber: 3 studentScore: 0.10 registrationTime: 2019-12-31 09:30:00.0
countryname: B studentNumber: 5 studentScore: null registrationTime: 2018-12-31 09:30:00.0
countryname: C studentNumber: 2 studentScore: 2.00 registrationTime: 2021-12-31 09:30:00.0
countryname: D studentNumber: 7 studentScore: 5.00 registrationTime: 2023-12-31 09:30:00.0
countryname: B studentNumber: 4 studentScore: 0.10 registrationTime: 2020-12-31 09:30:00.0
countryname: D studentNumber: 9 studentScore: 4.00 registrationTime: 2025-12-31 09:30:00.0
countryname: B studentNumber: 1 studentScore: 6.00 registrationTime: 2022-12-31 09:30:00.0
countryname: D studentNumber: 10 studentScore: null registrationTime: 2018-11-12 09:30:00.0
countryname: E studentNumber: 6 studentScore: 5.00 registrationTime: 2023-12-01 09:30:00.0
********studentList ordered**********
countryname: B studentNumber: 1 studentScore: 6.00 registrationTime: 2022-12-31 09:30:00.0
countryname: C studentNumber: 2 studentScore: 2.00 registrationTime: 2021-12-31 09:30:00.0
countryname: B studentNumber: 3 studentScore: 0.10 registrationTime: 2019-12-31 09:30:00.0
countryname: B studentNumber: 4 studentScore: 0.10 registrationTime: 2020-12-31 09:30:00.0
countryname: B studentNumber: 5 studentScore: null registrationTime: 2018-12-31 09:30:00.0
countryname: E studentNumber: 6 studentScore: 5.00 registrationTime: 2023-12-01 09:30:00.0
countryname: D studentNumber: 7 studentScore: 5.00 registrationTime: 2023-12-31 09:30:00.0
countryname: D studentNumber: 8 studentScore: 5.00 registrationTime: 2024-12-31 09:30:00.0
countryname: D studentNumber: 9 studentScore: 4.00 registrationTime: 2025-12-31 09:30:00.0
countryname: D studentNumber: 10 studentScore: null registrationTime: 2018-11-12 09:30:00.0