Comparator.comparing(…)嵌套字段

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

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

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

  return Comparator .comparing(Teacher::getAge); 

但是如何比较Lecture在嵌套字段上的比例呢?

  return Comparator .comparing(Lecture::getCourse::getTeacher:getAge) .thenComparing(Lecture::getCourse::getStudentSize); 

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

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

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

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

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

注意:在某些情况下,您需要明确说明generics类型。 例如,在Java 8中comparing(...)之前如果没有下面的代码将无法工作。

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

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

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

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

  • 通过组合比较器

     return comparing(Lecture::getCourse, comparing(Course::getTeacher, comparing(Teacher::getAge))) .thenComparing(Lecture::getCourse, comparing(Course::getStudentSize)); // or with separate comparators Comparator byAge = comparing(Teacher::getAge); Comparator byTeacherAge = comparing(Course::getTeacher, byAge); Comparator byStudentsSize = comparing(Course::getStudentSize); return comparing(Lecture::getCourse, byTeacherAge).thenComparing(Lecture::getCourse, byStudentsSize); 
  • 通过编写getter函数

     Function getCourse = Lecture::getCourse; return comparing(getCourse.andThen(Course::getTeacher).andThen(Teacher::getAge)) .thenComparing(getCourse.andThen(Course::getStudentSize)); // or with separate getters Function getCourse = Lecture::getCourse; Function teacherAge = getCourse.andThen(Course::getTeacher).andThen(Teacher::getAge); Function studentSize = getCourse.andThen(Course::getStudentSize); return comparing(teacherAge).thenComparing(studentSize); 
 import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.function.Function; class Person { String name ; PersonalDetail pDetail; public Person(String name, PersonalDetail pDetail) { super(); this.name = name; this.pDetail = pDetail; } public String getName() { return name; } public void setName(String name) { this.name = name; } public PersonalDetail getpDetail() { return pDetail; } public void setpDetail(PersonalDetail pDetail) { this.pDetail = pDetail; } } class PersonalDetail{ BirthDate birthDate; public BirthDate getBirthDate() { return birthDate; } public void setBirthDate(BirthDate birthDate) { this.birthDate = birthDate; } public PersonalDetail(BirthDate birthDate) { super(); this.birthDate = birthDate; } } class BirthDate { public String getBirthdate() { return birthdate; } public void setBirthdate(String birthdate) { this.birthdate = birthdate; } String birthdate; public BirthDate(String birthdate) { super(); this.birthdate = birthdate; } } public class Test1 { public static void main(String[] args) { BirthDate b1 = new BirthDate("2019-08-08"); BirthDate b2 = new BirthDate("2025-09-09"); BirthDate b3 = new BirthDate("2025-09-08"); BirthDate b4 = new BirthDate("2024-09-08"); PersonalDetail pd1 = new PersonalDetail(b1); PersonalDetail pd2 = new PersonalDetail(b2); PersonalDetail pd3 = new PersonalDetail(b3); PersonalDetail pd4 = new PersonalDetail(b4); Person p1 = new Person("P1",pd1); Person p2 = new Person("P2",pd2); Person p3 = new Person("P3",pd3); Person p4 = new Person("P4",pd4); List persons = new ArrayList(); persons.add(p1); persons.add(p2); persons.add(p3); persons.add(p4); Function getCourse = Person::getpDetail; Person minByAge = persons.stream() .max(Comparator.comparing(getCourse.andThen(PersonalDetail::getBirthDate).andThen(BirthDate::getBirthdate))).get(); System.out.println(maxByAge.getName()); } }