Comparison method violates its general contract

   今天一个群里哥们儿碰到一个异常,抛到群里求解答,他的代码如下图:

抛出的异常信息为:

Java代码  

  1. java.lang.IllegalArgumentException: Comparison method violates its general contract!  
  2. at java.util.TimSort.mergeHi(TimSort.java:868)  
  3. at java.util.TimSort.mergeAt(TimSort.java:485)  
  4. at java.util.TimSort.mergeCollapse(TimSort.java:408)  
  5. at java.util.TimSort.sort(TimSort.java:214)  
  6. at java.util.TimSort.sort(TimSort.java:173)  
  7. at java.util.Arrays.sort(Arrays.java:659)  
  8. at java.util.Collections.sort(Collections.java:217)  

 
 我说是compare方法实现的问题,他死活跟我掰,说我之前代码还好好的啊。没办法,我只好根据异常信息提示去翻JDK源码,异常里提示at Java.util.TimSort.mergeHi(TimSort.java:868)即TimSort类的mergeHi方法抛出的。于是我不断Google,找到了这篇帖子《why does my compare method throw exception — Comparison method violates its general contract》,根据他们的提示,我大概了解了compare方法需要返回1,-1,0即你的返回值要符合约定。

    于是我又按照异常提示看了Collections的sort方法源码,如图:

 继续跟踪Arrays类的sort方法:

 看到这里我基本就豁然开朗了,因为抛异常的地方是在TimSort类里,说明实际走的是else分支,所以有了第一种解决方法,添加-Djava.util.Arrays.useLegacyMergeSort=true这个JVM参数,其实要真正解决这个问题,要符合规范的实现compare方法,因为他写的代码里没有考虑对象o1和对象o2为Null的情况,即当o1与o2都为null时两者大小如何判定呢,当o1为null但o2不为null时两者大小又如何判定了呢,同理当o2为null但o1不为null时两者大小又如何判定呢又不得而知,或许你又会说,我这两个对象不可能为null,但那是你认为,JVM不知道,它只要求你的逻辑必须严谨,严格考虑各种情况下两者大小的判定原则。所以正确写法应该是:

Java代码  

  1. if(o1 == null && o2 == null) {  
  2.     return 0;  
  3. }  
  4. if(o1 == null) {  
  5.     return -1;  
  6. }  
  7. if(o2 == null) {  
  8.     return 1;  
  9. }  
  10. if(o1.getCreateTime() > o2.getCreateTime()) {  
  11.     return 1;  
  12. }  
  13. if(o2.getCreateTime() > o1.getCreateTime()) {  
  14.     return -1;  
  15. }  
  16. return 0;  

转载:http://iamyida.iteye.com/blog/2255804

时间: 2024-10-27 02:22:52

Comparison method violates its general contract的相关文章

Comparison method violates its general contract! 錯誤

问题描述 請問出現java.lang.IllegalArgumentException:Comparisonmethodviolatesitsgeneralcontract!的錯誤訊息查了網路確認是JDK1.7的關係有人說必須更嚴謹的編寫程式碼請問以下的程式碼應該要怎麼改才能避掉這個錯誤呢?謝謝各位的幫忙publicintcompare(Objectoa,Objectob){SortForObjecta=(SortForObject)oa;SortForObjectb=(SortForObjec

equals与“==”操作符的比较

equals方法是Object类的一个方法,所有继承自Object类的类都会集成此方法,并且可以重载这个方法来实现各自的比较操作,而且jdk也正是推荐这种做法.所以开发人员尽可以在自己的类中实现自己的equals方法来完成自己特定的比较功能,所以各个类的equals方法与= =之间并没有绝对的关系,这要根据各自类中自己的实现情况来看.也就是说可能会有两种情况发生:equals方法和= =相同或者不相同.在多数情况下这两者的区别就是究竟是对对象的引用进行比较还是对对象的值进行比较(其他特殊情况此处

Java equals 方法与hashcode 方法的深入解析

面试时经常会问起字符串比较相关的问题,比如:字符串比较时用的什么方法,内部实现如何?hashcode的作用,以及重写equal方法,为什么要重写hashcode方法?以下就为大家解答,需要的朋友可以参考下   PS:本文使用jdk1.7解析1.Object类 的equals 方法 复制代码 代码如下:    /**      * Indicates whether some other object is "equal to" this one.      * <p>   

java-equals()和hashCode()方法被隐式调用时的约定

问题描述 equals()和hashCode()方法被隐式调用时的约定 网上看到那么一个问题,百度了一下没有找到合适的答案...求大神解释下... 解决方案 JDK源码的注释说明的很清楚,如果重写了equal方法,也应该重写hashCode方法.看看源码注释吧,是非常好的文档资料呢. *Note that it is generally necessary to override the hashCode * method whenever this method is overridden s

《kafka中文手册》- 构架设计(一)

4. DESIGN 设计 4.1 Motivation 目的 4.2 Persistence 存储 Don't fear the filesystem! 不要对文件系统感到恐惧 Constant Time Suffices 常量耗时需求 4.3 Efficiency 效率 End-to-end Batch Compression 端到端的数据压缩 4.4 The Producer 发布者 Load balancing 负载均衡 Asynchronous send 异步发送 4.5 The Con

equals和hashCode源码解析

equals和hashCode网上也有很多的资料.这里只是记录下我目前的理解与认识.  大家会经常听到这样的话,当你重写equals方法时,尽量要重写hashCode方法,有些人却并不知道为什么要这样,待会就会给出源码说明这个原因.  首先来介绍下Object的equals和hashCode方法.如下:  ? 1 2 3 4 public native int hashCode(); public boolean equals(Object obj) {         return (this

[Java] 实现多线程的两种方法

版权声明:请尊重个人劳动成果,转载注明出处,谢谢! Java提供了两种创建线程方法: 通过实现Runable接口: 通过继承Thread类本身. 1 .声明实现 Runnable 接口的类,该类然后实现 run 方法.然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动.例如,计算大于某一规定值的质数的线程可以写成: class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { th

Java equals的一个坑

  public class StringEqualsObject { public static void main(String[] args) { String name="Tom"; Person p=new Person(name); System.out.println(name.equals(p)); System.out.println("p.toString():"+name.equals(p.toString())); System.out.pr

重写hashCode()和equals()方法

hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它为我们的编程提供便利的同时也带来了很多危险.这篇文章我们就讨论一下如何正解理解和使用这2个方法. 如何重写equals方法 如何重写hashCode方法 重写equals而不重写hashCode的风险 如何重写equals()方法 如果你决定要重写equals()方法,那么你一定要明确这么做所带来的风险,并确保自己能写出一个健壮的equals()方法.一定要注意的一点是,在重写equals()后,一定要重写has