自定义比较器按多个字段排序

问题描述

因为这个问题与我的上一个问题有关,所以我将link it here

假设我有一个包含两个整数的类TestB。我将能够在List<TestB> list上对a进行排序,然后在b上进行如下排序:

list.sort(Comparator.comparing(TestB::getA).thenComparing(TestB::getB));

现在,我想知道如何在最后一个答案中使用自定义比较器来做到这一点。

解决方法

Comparator的自定义list.sort(Comparator.comparing(TestB::getA).thenComparing(TestB::getB));版本是:

list.sort(new Comparator<>() {
    @Override
    public int compare(TestB b1,TestB b2) {
        int cmp = b1.getA().compareTo(b2.getA());
        if (cmp == 0)
            cmp = b1.getB().compareTo(b2.getB());
        return cmp;
    }
});
,

一种选择是使用我所谓的自定义通用多重比较器:

list2.sort(getComparator( p -> p.getTestB().getA(),p -> p.getTestB().getB() ));

private <T> Comparator<T> getComparator( Function<T,? extends Comparable<?>>... functions ) {
    
    return new Comparator<T>() {
        @Override
        public int compare(T obj1,T obj2) {
            
            for (Function<T,? extends Comparable<?>> function : functions) {
                Comparable<T> res1 = (Comparable<T>) function.apply(obj1);
                Comparable<T> res2 = (Comparable<T>) function.apply(obj2);
                
                int result = res1.compareTo((T) res2);
                
                if ( result != 0 ) {
                    return result;
                }
            }
            
            return 0;
        }
    };
}

它将根据功能参数的放置顺序从左到右排序。虽然会发出警告。因为它非常通用。 请记住,要比较的最终值的类型必须实现Comparator(Integer之类的原始类型已经实现了),并且您应该处理空问题(在这里我不做简短说明)。