按两个参数自定义排序无法正常工作

Custom sorting by two parameters not working correctly

public List<List<Integer>> demo(int[][] buildings) {
    List<List<Integer>> tracker = new ArrayList<>();
    int pointer = 0;
    for (int i = 0; i < buildings.length; i++) {
        tracker.add(Arrays.asList(buildings[i][0], -buildings[i][2]));
        tracker.add(Arrays.asList(buildings[i][1], buildings[i][2]));
    }
    Collections.sort(tracker, (a, b) -> {
        if (a.get(0) != b.get(0)) {
            return a.get(0).compareTo(b.get(0));
        } else {
            return a.get(1).compareTo(b.get(1));
        }
    });
    return tracker;
}

当我输入:

[[1,10001,10000],[2,10001,9999],[3,10001,9998]]

我得到的输出是:

[[1,-10000],[2,-9999],[3,-9998],[10001,10000],[10001,9999],[10001,9998]]

这不是我期望的输出,因为我的排序规则应该是10001 == 10001然后第二个坐标较小的应该排在最前面

我认为问题出在整数缓存上。对于低数字,整数被缓存,因此 != 有效。对于大数字,使用新的 Integers。使用 Integer.equals 检查是否相等。

变化:

if(a.get(0) != b.get(0))

进入:

if( a.get(0).equals(b.get(0)) )

否则你比较的是引用而不是值。

另一种方法是使用比较器的辅助方法class。

Comparator.<List<Integer>>comparing( list -> list.get(0) ).thenComparing(list-> list.get(1) );

准确无误。

这是修复它的另一种方法。不要比较值两次,即不要同时使用 equals() compareTo():

Collections.sort(tracker, (a, b) -> {
    int cmp = a.get(0).compareTo(b.get(0));
    if (cmp == 0) {
        cmp = a.get(1).compareTo(b.get(1));
    }
    return cmp;
} );

更简单的解决方案:

Collections.sort(tracker, Comparator.comparing(x -> x.get(0))
                                .thenComparing(x -> x.get(1)));

根据编译器的版本,可能需要“提示”才能知道 x 是什么。两者都应该做,没有一个比另一个更好。

Collections.sort(tracker, Comparator.<List<Integer>>comparing(x -> x.get(0))
                                               .thenComparing(x -> x.get(1)));
Collections.sort(tracker, Comparator.comparing((List<Integer> x) -> x.get(0))
                                .thenComparing(x -> x.get(1)));

在 Java 中比较对象时,始终使用 equals 或 compareTo(相应地)。

而不是:

   if(a.get(0) != b.get(0)){ // <---- THIS IS WRONG
        return a.get(0).compareTo(b.get(0));
    }

您已经可以重复使用 compareTo 结果:

a.get(0).compareTo(b.get(0));

即:

    int result = a.get(0).compareTo(b.get(0));
    return result == 0 ? a.get(1).compareTo(b.get(1)) : result;

此外,您可以简单地使用 tracker.sort 而不是 Collection.sort 并将比较逻辑替换为比较器链:

tracker.sort(Comparator.comparingInt((List<Integer> a) -> a.get(0))
                       .thenComparingInt(a -> a.get(1)));

一个运行例子:

public class A {

    public static List<List<Integer>> demo(int[][] buildings) {
        List<List<Integer>> tracker = new ArrayList<>();
        int pointer = 0;
        for (int[] building : buildings) {
            tracker.add(Arrays.asList(building[0], -building[2]));
            tracker.add(Arrays.asList(building[1], building[2]));
        }
        tracker.sort(Comparator.comparingInt((List<Integer> a) -> a.get(0))
               .thenComparingInt(a -> a.get(1)));
        return tracker;
    }


    public static void main(String[] args) {
        int[][] x = new int[][]{{1,10001,10000},{2,10001,9999},{3,10001,9998}};
        List<List<Integer>> demo = demo(x);
        demo.forEach(System.out::println);
    }
}

输出:

[1, -10000]
[2, -9999]
[3, -9998]
[10001, 9998]
[10001, 9999]
[10001, 10000]