Comparator.comparing(...) of a nested field

Solution 1:

You can't nest method references. You can use lambda expressions instead:

return Comparator
        .comparing(l->l.getCourse().getTeacher().getAge(), Comparator.reverseOrder()) 
        .thenComparing(l->l.getCourse().getStudentSize());

Without the need for reverse order it's even less verbose:

return Comparator
        .comparing(l->l.getCourse().getTeacher().getAge()) 
        .thenComparing(l->l.getCourse().getStudentSize());

Note: in some cases you need to explicitly state the generic types. For example, the code below won't work without the <FlightAssignment, LocalDateTime> before comparing(...) in Java 8.

flightAssignmentList.sort(Comparator
        .<FlightAssignment, LocalDateTime>comparing(a -> a.getFlight().getDepartureUTCDateTime())
        .thenComparing(a -> a.getFlight().getArrivalUTCDateTime())
        .thenComparing(FlightAssignment::getId));

Newer java version have better auto type detection and might not require that.

Solution 2:

Unfortunately there is no nice syntax in java for that.

If you want to reuse parts of comparator I can see 2 ways:

  • by composing comparators

    return comparing(Lecture::getCourse, comparing(Course::getTeacher, comparing(Teacher::getAge)))
           .thenComparing(Lecture::getCourse, comparing(Course::getStudentSize));
    
    // or with separate comparators
    Comparator<Teacher> byAge = comparing(Teacher::getAge);
    Comparator<Course> byTeacherAge = comparing(Course::getTeacher, byAge);
    Comparator<Course> byStudentsSize = comparing(Course::getStudentSize);
    return comparing(Lecture::getCourse, byTeacherAge).thenComparing(Lecture::getCourse, byStudentsSize);
    
  • by composing getter functions

    Function<Lecture, Course> getCourse = Lecture::getCourse;            
    return comparing(getCourse.andThen(Course::getTeacher).andThen(Teacher::getAge))
           .thenComparing(getCourse.andThen(Course::getStudentSize));
    
    // or with separate getters
    Function<Lecture, Course> getCourse = Lecture::getCourse;
    Function<Lecture, Integer> teacherAge = getCourse.andThen(Course::getTeacher).andThen(Teacher::getAge);
    Function<Lecture, Integer> studentSize = getCourse.andThen(Course::getStudentSize);
    return comparing(teacherAge).thenComparing(studentSize);