Comparator.comparing(…) of a nested field

前端 未结 3 868
轻奢々
轻奢々 2020-11-30 09:53

Suppose I have a domain model like this:

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

class Course {
     Teacher teacher;
     int studentSize         


        
相关标签:
3条回答
  • 2020-11-30 10:12

    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.

    0 讨论(0)
  • 2020-11-30 10:22
    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<Person> persons = new ArrayList();
               persons.add(p1);
               persons.add(p2);
               persons.add(p3);
               persons.add(p4);
    
               Function<Person, PersonalDetail> getCourse = Person::getpDetail;  
    
               Person minByAge = persons.stream()
                          .max(Comparator.comparing(getCourse.andThen(PersonalDetail::getBirthDate).andThen(BirthDate::getBirthdate))).get();
    
    
              System.out.println(maxByAge.getName());
    
           }
    
        }
    
    0 讨论(0)
  • 2020-11-30 10:31

    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);
      
    0 讨论(0)
提交回复
热议问题