按两个参数自定义排序无法正常工作
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
然后第二个坐标较小的应该排在最前面
我认为问题出在整数缓存上。对于低数字,整数被缓存,因此 !=
有效。对于大数字,使用新的 Integer
s。使用 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]
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
然后第二个坐标较小的应该排在最前面
我认为问题出在整数缓存上。对于低数字,整数被缓存,因此 !=
有效。对于大数字,使用新的 Integer
s。使用 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]