Comparator.comparing(...)嵌套字段

Geo*_*met 18 java lambda comparator java-8

假设我有一个这样的域模型:

class Lecture {
     Course course;
     ... // getters
}

class Course {
     Teacher teacher;
     int studentSize;
     ... // getters
}

class Teacher {
     int age;
     ... // getters
}
Run Code Online (Sandbox Code Playgroud)

现在我可以像这样创建一个教师比较器:

    return Comparator
            .comparing(Teacher::getAge);
Run Code Online (Sandbox Code Playgroud)

但是,我如何比较Lecture的嵌套字段,像这样?

    return Comparator
            .comparing(Lecture::getCourse::getTeacher:getAge) 
            .thenComparing(Lecture::getCourse::getStudentSize);
Run Code Online (Sandbox Code Playgroud)

我无法Lecture.getTeacherAge()在模型上添加方法.

Era*_*ran 24

您不能嵌套方法引用.您可以使用lambda表达式:

return Comparator
        .comparing(l->l.getCourse().getTeacher().getAge(), Comparator.reverseOrder()) 
        .thenComparing(l->l.getCourse().getStudentSize());
Run Code Online (Sandbox Code Playgroud)

不需要逆序,它甚至更简洁:

return Comparator
        .comparing(l->l.getCourse().getTeacher().getAge()) 
        .thenComparing(l->l.getCourse().getStudentSize());
Run Code Online (Sandbox Code Playgroud)

注意:在某些情况下,您需要明确说明泛型类型.例如,如果没有Java 8中的<FlightAssignment, LocalDateTime>before comparing(...),下面的代码将无法工作.

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

较新的java版本具有更好的自动类型检测,可能不需要.

  • 我知道这是一篇旧帖子,但对 Eran 的这个帖子有两个巨大的赞誉。第三个选项,明确说明类型确实帮助我解决了问题。 (3认同)

Naz*_*iuk 10

不幸的是,java中没有很好的语法.

如果你想重用部分比较器我可以看到两种方式:

  • 通过组合比较器

    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);
    
    Run Code Online (Sandbox Code Playgroud)
  • 通过编写getter函数

    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);
    
    Run Code Online (Sandbox Code Playgroud)