如何将父类Comparator与子类Comparator结合使用?
问题:如何结合父类比较器与子类特定比较器排序
场景代码
父类定义
@Data public class Parent { private String xx; private int yy; }
子类定义
@Data public class ChildA extends Parent { private String aa; } @Data public class ChildB extends Parent { private String bb; }
比较器定义
// 父类公共比较器 Comparator<Parent> commonComparator = Comparator.comparing(Parent::getYy) .thenComparing(Parent::getXx); // 子类特定比较器 Comparator<ChildA> childAComparator = Comparator.comparing(ChildA::getAa); Comparator<ChildB> childBComparator = Comparator.comparing(ChildB::getBb);
问题与错误
尝试对ChildA列表排序时,直接结合两个比较器:
commonComparator.thenComparing(childAComparator);
出现编译错误:
类型Comparator中的方法thenComparing(Comparator<? super Parent>)不适用于参数(Comparator
)
错误原因
commonComparator的类型是Comparator<Parent>,其thenComparing方法要求传入的比较器类型为Comparator<? super Parent>。但Comparator<ChildA>的泛型是ChildA(Parent的子类),并不符合? super Parent的要求(该通配符代表Parent或其父类),因此类型不匹配。
解决方案
方案1:安全类型转换适配子类
利用Comparator的逆变特性,将父类比较器转换为支持子类的比较器,再结合子类特定比较器:
// 转换为适用于ChildA的父类比较器,该转换安全,因为ChildA继承自Parent Comparator<ChildA> parentComparatorForChildA = (Comparator<ChildA>) (Comparator<? super ChildA>) commonComparator; // 结合两个比较器 Comparator<ChildA> combinedComparator = parentComparatorForChildA.thenComparing(childAComparator);
方案2:泛型方法复用父类比较逻辑
定义一个泛型方法,生成适用于任意Parent子类的公共比较器,避免类型转换:
// 泛型方法:生成适用于所有Parent子类的公共比较器 public static <T extends Parent> Comparator<T> getCommonComparator() { return Comparator.comparing(T::getYy) .thenComparing(T::getXx); } // 结合子类比较器 Comparator<ChildA> combinedComparator = getCommonComparator() .thenComparing(childAComparator);
方案3:直接构建子类专属的组合比较器
如果不想额外定义方法,可直接针对ChildA重复父类比较逻辑,再结合子类特定规则:
Comparator<ChildA> combinedComparator = Comparator.comparing(ChildA::getYy) .thenComparing(ChildA::getXx) .thenComparing(childAComparator);
内容的提问来源于stack exchange,提问作者Paul Marcelin Bejan
相关产品推荐
相关产品推荐

