[英]Comparator Sorting
Please find the code below: 请在下面找到代码:
Collections.sort(longList, new Comparator<Long>() {
public int compare(long m1, long m2) {
return (int) (m2 - m1);
}
For some input it throws the following error: 对于某些输入,它将引发以下错误:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:763)
at java.util.TimSort.mergeAt(TimSort.java:499)
at java.util.TimSort.mergeForceCollapse(TimSort.java:442)
at java.util.TimSort.sort(TimSort.java:239)
at java.util.TimSort.sort(TimSort.java:189)
at java.util.Arrays.sort(Arrays.java:867)
at java.util.Collections.sort(Collections.java:229)
Please help! 请帮忙!
I'm assuming you have a typo in the question and the actual signature of the compare method is int compare(Long m1, Long m2)
, or your code wouldn't pass compilation at all, which is not the issue you describe. 我假设您在该问题中有错字,并且compare方法的实际签名是
int compare(Long m1, Long m2)
,否则您的代码根本不会通过编译,这不是您所描述的问题。
The actual issue is that you are trying to compare two longs by returning the difference between them cast to int
. 实际的问题是,您试图通过将两个long的差值返回给
int
来比较两个long。 This may give you incorrect results when the difference is not within the range of the int
type. 当差值不在
int
类型范围内时,这可能会给您带来不正确的结果。 You can use return m2.compareTo(m1)
instead (or return m2 < m1 ? -1 : m2 > m1 ? 1 : 0
if you don't want to rely on Long
's compareTo
implementation). 您可以改用
return m2.compareTo(m1)
(如果不想依赖Long
的compareTo
实现,则return m2 < m1 ? -1 : m2 > m1 ? 1 : 0
)。
Doing this: 这样做:
Comparator<Long> d = new Comparator<Long>() {
public int compare(long m1, long m2) {
return (int) (m2 - m1);
}
};
is the same as NOT implementing the abstract method in the comparator interface 是一样的,在比较器接口NOT实现抽象方法
public int compare(T a1, T a2);
so your code is not compiling 所以你的代码没有编译
you should use (is java8) the method reference 您应该使用(是java8)方法参考
Comparator<Long> d = Long::compare;
but what is wrong whit this: (int) (m2 - m1);
但是这是怎么回事:
(int) (m2 - m1);
may you be asking yourself... 也许你在问自己...
well you are forcing a cast of 2 a long into a integer, so that result can be a very negative Long or a positive integer 好吧,您正在强制将2的long强制转换为整数,以便结果可以是非常负的Long或正整数
check this example to clarify: 检查此示例以澄清:
long b = 1000_000_000_000_000L;
long a = 100L;
System.out.println(a - b);
System.out.println((int) (a - b));
the result is as long 结果是一样长
-999999999999900
-999999999999900
as int 作为int
1530495076
1530495076
which is definitely breaking the comparation results 这肯定打破了比较结果
List<Long> list = Arrays.asList(3L, 2L, 1L);
list.sort(new Comparator<Long>() {
@Override
public int compare(Long o1, Long o2) {
return o1.compareTo(o2);
}
});
System.out.println(list);
OR: 要么:
List<Long> list = Arrays.asList(3L, 2L, 1L);
list.sort(Long::compareTo);
System.out.println(list);
There are two things worth mentioning here: 这里有两件事值得一提:
In other words: instead of doing 换句话说:而不是做
int compare(Long l1, long l2) {
return l2 - l1;
you could do: 你可以做:
return l2.compareTo(l1);
instead. 代替。 That is just easier to read;
那更容易阅读; and performance is basically the same.
和性能基本相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.