Issue
I have a parent class
@Data
public class Parent {
private String xx;
private int yy;
}
and two child classes that extends the parent class
@Data
public class ChildA extends Parent {
private String aa;
}
@Data
public class ChildB extends Parent {
private String bb;
}
P.S. for semplicity the fields of Parent and ChildA, ChildB are few, but there are many more.
I have a common comparator:
Comparator<Parent> commonComparator = Comparator.comparing(Parent::getYy)
.thenComparing(Parent::getXx);
and specific comparator for each child:
Comparator<ChildA> childAComparator = Comparator.comparing(ChildA::getAa);
Comparator<ChildB> childBComparator = Comparator.comparing(ChildB::getBb);
If I want to sort the a List of ChildA, how can I combine the commonComparator with the childAComparator ?
I tried :
commonComparator.thenComparing(childAComparator);
but I got an issue:
The method thenComparing(Comparator<? super Parent>) in the type Comparator is not applicable for the arguments (Comparator< ChildA >)
Solution
I don't think there is a function in the core libraries that will compose these comparators for you. But it is a simple function:
private static <T> Comparator<T> compose(
Comparator<? super T> before,
Comparator<T> after) {
return (o1, o2) -> {
int diff = before.compare(o1, o2);
return diff == 0 ? after.compare(o1, o2) : diff;
};
}
Then you can use it as
private static final Comparator<ChildA> combined =
compose(commonComparator, childAComparator);
Note that because thenComparing()
has bounds of ? super T
, it can only compose the two comparators when the child comparator is applied first, but in this case, the parent comparator must be applied first.
Answered By - erickson
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)