【发布时间】:2018-07-01 07:28:36
【问题描述】:
我遇到了以下异常,但我不太明白为什么:
java.lang.IllegalArgumentException:比较方法违反了它的 总承包!
在 java.util.TimSort.mergeLo(TimSort.java:777) 在 java.util.TimSort.mergeAt(TimSort.java:514) 在 java.util.TimSort.mergeCollapse(TimSort.java:441) 在 java.util.TimSort.sort(TimSort.java:245) 在 java.util.Arrays.sort(Arrays.java:1512) 在 java.util.ArrayList.sort(ArrayList.java:1454)
我编写了以下 JUnit 测试来验证行为:
@Test
public void testComparator() {
List<Boolean> item = new ArrayList<>();
item.add(true);
for (int i = 0; i < 1000000; i++) {
item.add(false);
}
while(true) {
System.out.println("Sorting");
Collections.shuffle(item);
item.sort((lineItem1, lineItem2) -> {
if (lineItem1 && lineItem2) {
return 0;
} else if (!lineItem1) {
return 1;
} else if (!lineItem2 ) {
return -1;
}
return 0;
});
}
}
如果我交换 return 1 和 return -1,它会毫无例外地突然工作。 但为什么?这应该只改变排序顺序而不破坏整个比较器。
我错过了什么?
【问题讨论】:
-
已经检查this?
-
您违反了合同,因为您当前在 lineItem1 为 false 时返回 1,无论 lineItem2 具有什么值。但如果两者都是 false,则需要返回 0。
-
你试过比较(假,假)吗?
-
@C.Koenig compare(A=false, B=false) 返回 1 但 compare(B=false, A=false) 也返回 1。那么在这种情况下,哪个排序更高:甲还是乙?毕竟两者都比另一个大。
-
如果可以允许我就这个主题发表我的演讲...... 第 1 部分:youtu.be/Enwbh6wpnYs ... 第 2 部分:youtu.be/bvnmbRo7a1Y
标签: java java-8 comparator