我在整理集合时遇到以下错误。
Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:777)
at java.util.TimSort.mergeAt(TimSort.java:514)
at java.util.TimSort.mergeCollapse(TimSort.java:441)
at java.util.TimSort.sort(TimSort.java:245)
这是比较器和使用它的流。
Comparator<Task> comparator = comparing(Task::getAssigneeSite, nullsLast(naturalOrder())).thenComparing(Task::getDueDate,
nullsLast(naturalOrder()));
Collection<Task> groupTasks = findTasks(site, dossierAdministratorGroup).stream()
.sorted(comparator)
.collect(toList());
对于类似的问题,我找到了以下答案:
例外'比较法违反其一般约定!'比较一个对象的两个日期属性时
但我看不出这如何解决问题。只有当bean本身可以为null时,将比较器包装在null中才有用,但事实并非如此(任务从不为null)。
根据我的理解,nullsLast(...)”表示空值应被视为大于“assigneeSite”对象,DueDate也是如此。所以我被什么是违约难住了。
有没有人能解释一下这个比较器内部发生的契约违约?
所以,这对我来说可能非常愚蠢,但问题出在“Site”类中已经存在的比较器中,我没有验证。
@Override
public int compareTo(Site other) {
if (this.code < other.getCode()) {
return -1;
} else {
return 1;
}
}
这里有一个明显的问题,因为比较器没有指定两个代码字段相等的情况。除此之外,它也没有考虑到任何一个 Integer 对象可能是空的。
一个正确的null安全实现(使用java 8的Comparator.comparing方法)将是:
return comparing(Site::getCode, nullsLast(naturalOrder())).compare(this, other);
我把这个答案放在这里是为了提醒其他人在遇到违反合同的错误时检查所有的比较器。
我已经在类上实现了Comaprable,它给了我比较方法违反了它的总合同!,由于有一些值返回为 null,代码如下 公共静态比较器名称比较器 = 新比较器() {
我试图使用比较器基于两个字符串的比较对数组列表进行排序,但我最终使用的比较方法违反了它的一般契约错误。如果字符串中出现空值比较,我该如何处理? 密码 错误
我认为下面的comprator实现是错误的。它会给我一个字符串的排序。但当我使用这个实现对List进行排序时,它不会抛出以下异常:“java.lang.IllegalArgumentException:Comparison方法违反了它的一般约定!” 问:为什么上面的异常不是由 Collections.sort(list, new WrongComparator()) 方法调用抛出的?
问题内容: 有人可以简单地向我解释一下,为什么此代码会引发异常,“比较方法违反了它的一般约定!”,我该如何解决? 问题答案: 你的比较器不是可传递的。 让是的父,并成为母公司。既然和,那一定是这样。但是,如果在和上调用比较器,它将返回零,即。这违反了合同,因此引发异常。 该库可以很好地检测到这一点并让你知道,而不是行为不规律。 满足传递性要求的一种方法是遍历整个链,而不仅仅是查看直接祖先。
比较器的JavaDoc指出 强烈建议(尽管不是必需的)自然顺序与相等一致。 他们还举了一个“奇怪”行为的例子,当<代码>(a.equals(b) 现在,有人能给我举一个例子说明在case
偏离变量只是包含以下字段的对象的一个实例: 附言时间对象是来自 Joda-Time 库的 DateTime 实例,TransportType 是包含常量火车、海船、驳船和卡车的枚举。 编辑: 好的,所以我将比较器编辑为以下内容: 但这显然违反了一般契约。我如何让它按时间排序,然后根据它们的其他属性对那些具有相等时间的对象进行排序,只关心它们是否相等?希望这有意义… 编辑:解决方案 谢谢大家回答我的