[英]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;
}
When I input:当我输入:
[[1,10001,10000],[2,10001,9999],[3,10001,9998]]
the output I get is:我得到的 output 是:
[[1,-10000],[2,-9999],[3,-9998],[10001,10000],[10001,9999],[10001,9998]]
This is not the output that I expect, because my sorting rule is supposed to be when 10001 == 10001
then the ones with smaller second coordinates should be arranged at first.这不是我期望的 output,因为我的排序规则应该是当
10001 == 10001
时,应该首先排列具有较小第二坐标的那些。
I think the issue is Integer caching.我认为问题是 Integer 缓存。 For the low numbers, the Integer is cached so
!=
works.对于低数字, Integer 被缓存,因此
!=
有效。 For the large numbers, new Integer
s are used.对于大数字,使用新的
Integer
。 Use Integer.equals to check for equality.使用 Integer.equals 检查是否相等。
Change:改变:
if(a.get(0) != b.get(0))
Into:进入:
if( a.get(0).equals(b.get(0)) )
Otherwise you're comparing the reference not the value.否则,您是在比较参考而不是值。
Another way would be to use the helper methods of the Comparator class.另一种方法是使用比较器 class 的辅助方法。
Comparator.<List<Integer>>comparing( list -> list.get(0) ).thenComparing(list-> list.get(1) );
Answer by matt is spot on.马特的回答很到位。
Here is an alternative way to fix it.这是修复它的另一种方法。 Don't compare values twice, ie don't use both
equals()
and compareTo()
:不要两次比较值,即不要同时使用
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;
} );
Even easier solution:更简单的解决方案:
Collections.sort(tracker, Comparator.comparing(x -> x.get(0))
.thenComparing(x -> x.get(1)));
Depending on the version of the compiler, it may need a "hint" to know what x
is.根据编译器的版本,它可能需要一个“提示”才能知道
x
是什么。 Either of these should do it, neither is better than the other.这些中的任何一个都应该这样做,没有一个比另一个更好。
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)));
When comparing object in Java always use equals or compareTo (accordingly).在比较 Java 中的 object 时,始终使用 equals 或 compareTo(相应地)。
Instead of:代替:
if(a.get(0) != b.get(0)){ // <---- THIS IS WRONG
return a.get(0).compareTo(b.get(0));
}
You can reused already the compareTo
result of:您可以重复使用以下的
compareTo
结果:
a.get(0).compareTo(b.get(0));
namely:即:
int result = a.get(0).compareTo(b.get(0));
return result == 0 ? a.get(1).compareTo(b.get(1)) : result;
Moreover instead of Collection.sort
you can simply used tracker.sort and replaced the comparison logic with a Comparator chain:此外,您可以简单地使用 tracker.sort 并将比较逻辑替换为 Comparator 链,而不是
Collection.sort
:
tracker.sort(Comparator.comparingInt((List<Integer> a) -> a.get(0))
.thenComparingInt(a -> a.get(1)));
A running example:一个运行的例子:
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);
}
}
OUTPUT: OUTPUT:
[1, -10000]
[2, -9999]
[3, -9998]
[10001, 9998]
[10001, 9999]
[10001, 10000]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.