java 嵌套字段的 Comparator.comparing(...)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38533338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Comparator.comparing(...) of a nested field
提问by Geoffrey De Smet
Suppose I have a domain model like this:
假设我有一个这样的域模型:
class Lecture {
Course course;
... // getters
}
class Course {
Teacher teacher;
int studentSize;
... // getters
}
class Teacher {
int age;
... // getters
}
Now I can create a Teacher Comparator like this:
现在我可以像这样创建一个教师比较器:
return Comparator
.comparing(Teacher::getAge);
But how do I compare Lecture's on nested fields, like this?
但是我如何在嵌套字段上比较 Lecture,就像这样?
return Comparator
.comparing(Lecture::getCourse::getTeacher:getAge)
.thenComparing(Lecture::getCourse::getStudentSize);
I can't add a method Lecture.getTeacherAge()
on the model.
我无法Lecture.getTeacherAge()
在模型上添加方法。
回答by Eran
You can't nest method references. You can use lambda expressions instead:
您不能嵌套方法引用。您可以改用 lambda 表达式:
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.
注意:在某些情况下,您需要明确说明泛型类型。例如,如果没有Java 8 中的<FlightAssignment, LocalDateTime>
before comparing(...)
,下面的代码将无法运行。
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.
较新的 java 版本具有更好的自动类型检测,可能不需要。
回答by Nazarii Bardiuk
Unfortunately there is no nice syntax in java for that.
不幸的是,java 中没有很好的语法。
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);
通过组合比较器
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);
通过组合 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);
回答by manish garg
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());
}
}