次のようなドメインモデルがあるとします。
_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()
を追加できません。
メソッド参照をネストすることはできません。代わりにラムダ式を使用できます。
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バージョンの方が自動タイプ検出が優れており、それを必要としない場合があります。
残念ながら、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);
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());
}
}