web-dev-qa-db-ja.com

ネストされたフィールドのComparator.comparing(...)

次のようなドメインモデルがあるとします。

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

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

class Teacher {
     int age;
     ... // getters
}
_

これで、次のようなTeacher Comparatorを作成できます。

_    return Comparator
            .comparing(Teacher::getAge);
_

しかし、このようにネストされたフィールドでの講義を​​比較するにはどうすればよいですか?

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

モデルにメソッドLecture.getTeacherAge()を追加できません。

24

メソッド参照をネストすることはできません。代わりにラムダ式を使用できます。

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());

注:場合によっては、ジェネリック型を明示的に指定する必要があります。たとえば、以下のコードは、Java 8.のcomparing(...)の前に<FlightAssignment, LocalDateTime>がないと機能しません。

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

新しいJavaバージョンの方が自動タイプ検出が優れており、それを必要としない場合があります。

34
Eran

残念ながら、Javaにはそのための良い構文はありません。

コンパレータの一部を再利用したい場合は、2つの方法があります。

  • コンパレータを構成することにより

    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);
    
  • ゲッター関数を作成する

    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);
    
11
Nazarii Bardiuk
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
manish garg