【问题标题】:Custom Comparator sort with multiple fields具有多个字段的自定义比较器排序
【发布时间】:2020-08-27 20:20:52
【问题描述】:

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

假设我有一个类TestB 有两个整数。我可以像这样在a 上对List<TestB> list 排序,然后在b 上排序:

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

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

【问题讨论】:

  • 这个问题不清楚,至少对我来说是这样。帮助我们帮助您 - 分享一些示例数据以及您希望获得的结果

标签: java sorting object comparator


【解决方案1】:

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

【讨论】:

  • 当我尝试上面的代码“无法在原始类型 int 上调用 compareTo(int)”时出现此错误。它适用于 Integer.compare() 很好
  • @heapoverflow 您的代码调用的是comparing(),而不是comparingInt(),导致假设ab 是对象,而不是原语。如果aint,请改用Integer.compare(b1.getA(), b2.getA())。与其他原语类似,在适当的类上使用compare() 方法(LongDouble,...)。 --- 仅供参考:虽然comparing() 为您工作,但使用comparingInt() 可以防止原语不必要的自动装箱
【解决方案2】:

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

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 问题(为了简短起见,我在这里没有这样做)。

【讨论】:

  • 好的,谢谢,我希望有一个优雅而简单的解决方案。我会等待更多的答案
猜你喜欢
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 2013-11-04
  • 1970-01-01
  • 1970-01-01
  • 2022-07-22
  • 1970-01-01
相关资源
最近更新 更多