具有多个字段的自定义比较器排序

Custom Comparator sort with multiple fields

因为这个问题和我上一个问题有关,所以我会

假设我有一个 class TestB 和两个整数。我可以在 a 上对 List<TestB> list 排序,然后在 b 上排序,如下所示:

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

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

一种选择是使用我所说的自定义通用 multi-comparator:

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 这样的原始类型已经实现了)并且你应该处理 null 问题(我没有在这里做以保持简短)。

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

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;
    }
});