1. 程式人生 > >java 【排序】異常:java.lang.IllegalArgumentException: Comparison method violates its general contract!

java 【排序】異常:java.lang.IllegalArgumentException: Comparison method violates its general contract!

環境

java:1.7

前言

本來是不想寫這篇的,但是最近老報這個錯誤,一開始,我以為解決了,後來發現不是那麼回事

現在特意記錄下

我的排序程式碼

我先貼出完整的排序程式碼:

/**
 * 支援兩個欄位排序
 * @param result
 * @param order
 * @param orderType
 * @param twoOrder 第二排序欄位
 * @param twoType 第二排序順序
 * @return
 * @author yutao
 * @date 2018年5月24日下午3:00:03
 */
public static List<Map<String, Object>> resultOrder
(List<Map<String, Object>> result, String order, Integer orderType, final String twoOrder, final Integer twoType){ if(result == null || orderType == null){ return result; } if(orderType != -1){ orderType = 1
; } final String orderKey = order; final Integer oType = orderType; Collections.sort(result, new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { Object obj1 = o1.get(orderKey); Object obj2 = o2.get(orderKey); return
commonOrder(orderKey, oType, obj1, obj2, twoOrder, twoType); } }); return result; } /** * 公共的排序部分 * @param orderKey * @param oType * @param obj1 * @param obj2 * @param twoOrder * @param twoType * @return * @author yutao * @date 2018年5月24日下午3:19:37 */ public static Integer commonOrder(final String orderKey, final Integer oType, Object obj1, Object obj2, String twoOrder, Integer twoType) { //重點注意 if(obj1 == null && obj2 == null){ return 0; } if (obj1 == null) { if(oType < 0){ return -oType; } return oType; } if (obj2 == null) { if(oType < 0){ return oType; } return -oType; } if(obj1 instanceof Date && obj2 instanceof Date){ //日期排序 Date date1 = (Date)obj1; Date date2 = (Date)obj2; return longCompare(oType, date1.getTime(), date2.getTime(), twoOrder, twoType); }else if(obj1 instanceof String && obj2 instanceof String){ //字串排序 String str1 = obj1.toString(); String str2 = obj2.toString(); if(str1.compareTo(str2) < 0){ return -oType; }else if(str1.compareTo(str2) == 0){ return 0; }else if(str1.compareTo(str2) > 0){ return oType; } }else if((obj1 instanceof Double || obj1 instanceof Float) && (obj2 instanceof Double || obj2 instanceof Float)){ //浮點型排序 return doubleCompare(oType, obj1, obj2, twoOrder, twoType); }else if((obj1 instanceof Long || obj1 instanceof Integer || obj1 instanceof Short || obj1 instanceof Byte) && (obj2 instanceof Long || obj2 instanceof Integer || obj2 instanceof Short || obj2 instanceof Byte)){ //整數型排序 return longCompare(oType, obj1, obj2, twoOrder, twoType); }else if((obj1.getClass() != obj2.getClass()) && (obj1 instanceof Number && obj2 instanceof Number)){ //這種情況可能是,既有整數又有浮點數 return doubleCompare(oType, obj1, obj2, twoOrder, twoType); } return 0; } /** * 整形比較大小 * @param oType * @param obj1 * @param obj2 * @param twoOrder * @param twoType * @return * @author yutao * @date 2018年5月24日下午3:09:18 */ private static int longCompare(final Integer oType, Object obj1, Object obj2, String twoOrder, Integer twoType) { long d1 = Long.parseLong(obj1.toString()); long d2 = Long.parseLong(obj2.toString()); if(d1 < d2){ return -oType; }else if(d1 == d2){ if(twoOrder != null && twoType != null){ //相等就使用第二欄位排序 return commonOrder(twoOrder, twoType, obj1, obj2, null, null); } //相同的是否進行互動 return 0; }else if(d1 > d2){ return oType; } return 0; } /** * 浮點型比較大小 * @param oType * @param obj1 * @param obj2 * @return * @author yutao * @date 2018年5月24日下午3:09:41 */ private static int doubleCompare(final Integer oType, Object obj1, Object obj2, String twoOrder, Integer twoType) { double d1 = Double.parseDouble(obj1.toString()); double d2 = Double.parseDouble(obj2.toString()); if(d1 < d2){ return -oType; }else if(d1 == d2){ if(twoOrder != null && twoType != null){ //相等就使用第二欄位排序 return commonOrder(twoOrder, twoType, obj1, obj2, null, null); } return 0; }else if(d1 > d2){ return oType; } return 0; }

分析

在JDK7以後,實現Comparable介面後,要滿足一下三個特性:
1) 自反性:x,y 的比較結果和 y,x 的比較結果相反。
2) 傳遞性:x>y,y>z,則 x>z。
3) 對稱性:x=y,則 x,z 比較結果和 y,z 比較結果相同。

而我的程式碼中,因為有物件屬性為null的判斷,所以有下面這樣的程式碼:

public static Integer commonOrder(final String orderKey, final Integer oType, Object obj1, Object obj2, String twoOrder, Integer twoType) {
    if (obj1 == null) {
        if(oType < 0){
            return -oType;
        }
        return oType;
    }
    if (obj2 == null) {
        if(oType < 0){
            return oType;
        }
    return -oType;
}
// 以下程式碼省略。。。

這樣的話,是不滿足對稱性的;
因為必須完善為null的情況:

public static Integer commonOrder(final String orderKey, final Integer oType, Object obj1, Object obj2, String twoOrder, Integer twoType) {
    //重點注意 
    if(obj1 == null && obj2 == null){
        return 0;
    }
    if (obj1 == null) {
        if(oType < 0){
            return -oType;
        }
        return oType;
    }
    if (obj2 == null) {
        if(oType < 0){
            return oType;
        }
    return -oType;
}
// 以下程式碼省略。。。

有了上面的程式碼,就滿足對稱性了。

相關推薦

java 排序異常java.lang.IllegalArgumentException: Comparison method violates its general contract!

環境 java:1.7 前言 本來是不想寫這篇的,但是最近老報這個錯誤,一開始,我以為解決了,後來發現不是那麼回事 現在特意記錄下 我的排序程式碼 我先貼出完整的排序程式碼: /** * 支援兩個欄位排序 * @param result

java.lang.IllegalArgumentException: Comparison method violates its general contract!的解決方法

       上午在敲程式碼時,對一個List集合進行排序,程式碼如下: Collections.sort(list2,new Comparator<Integer>()

java.lang.IllegalArgumentException: Comparison method violates its general contract!

背景 16號為了統一線上伺服器執行環境,將兩臺伺服器的Tomcat6+JDK6升級到Tomcat7+JDK7,本以為很簡單的事情,升級後自己驗證也沒問題,沒想到卻悲劇了。升級後,過了半小時運營就找過來反饋問題,部分角色無法登陸系統,由於異常日誌沒有輸出,沒有找

java-collections.sort異常Comparison method violates its general contract!

異常資訊 java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.util.TimSort.mergeHi(TimSort.java:868

排序這個坑,你要注意Comparison method violates its general contract!

解決方法如下: /** * 對比類:根據持有金額 */ private static class TenderCollectComparator implements Comparator<TenderCollect> { public int compa

集合排序中的 Comparison method violates its general contract 異常

異常資訊 java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.util.TimSort.mergeHi(TimSort.java:86

[Java]實現Comparable介面不嚴謹導致Comparison method violates its general contract!

/** * 已經將src陣列複製了一份到dest陣列 * low和high是mergesort在陣列中的下標 * off為low相對於下標0的偏移量 */ private static void mergeSort(Object[] src,

Android碰到 "Comparison method violates its general contract" 異常的解決方法

1.概述:  最近在對資訊進行排序時,做了一個簡單地比較器,當時在執行時並沒有報錯,但是,後臺資料重新整理時,我這邊就出了問題。在jdk1.6中,當我們比較的內容的值相同時,使用java自己的排序方法"Collections.sort()"是很正常的,可是到了jdk1.7,

這個坑,你要注意Comparison method violates its general contract!

背景有部分業務需要進行排序,對比的物件是某實體裡的金額(double 型別),這樣,我們實現了自定義的比較類,結果執行一段時間之後報了錯誤:Comparison method violates its general contract! ,經過校驗,發現錯誤出現在自定義排序上

Java工具推薦GeneratorJava程式碼生成工具

歡迎來到 Generator 寫這個程式碼生成器工具的想法源自2018年3月份,當時專案組剛完成一個Java Web專案的研發工作,在整個專案過程中耗費了不少的時間來構建SpringMVC的重複性程式碼和Mybatis的對映檔案,同時我也越來越覺得這些重複且難度不大的工作不

深入Java虛擬機器之一Java記憶體區域與記憶體溢位

記憶體區域     Java虛擬機器在執行Java程式的過程中會把他所管理的記憶體劃分為若干個不同的資料區域。Java虛擬機器規範將JVM所管理的記憶體分為以下幾個執行時資料區:程式計數器、Java虛擬機器棧、本地方法棧、Java堆、方法區。下面詳細闡述各資料區所儲存的資料型

我的Android進階之旅Android 7.0報異常java.lang.SecurityException: COLUMN_LOCAL_FILENAME is deprecated;

之前開發的一個和第三方合作的apk,在之前公司的 Android 5.1 系統的手錶上執行正常,今天在公司新開發的 Android 7.1系統的手錶上執行的時候,使用 DownloadManager 下載之後,查詢下載狀態的時候,報了異常 java.lan

Spring錯誤筆記系列自己new出來的bean中被@Autowired註解修飾的屬性報空指標異常java.lang.NullPointException

自己new出來的bean中被@Autowired註解修飾的屬性報空指標異常 異常描述 原本我再測試RabbitMQ的傳送程式,裡面用到了一個AmqpTemplate介面,用了@Autowired註解。但是當我使用AmqpTemplate的conver

Springboot(Eureka)啟動異常java.lang.NoSuchMethodError:已解決

根本原因是parent 中的version 版本過高 現階段預設版本2.0.1 將版本改為1.4.0之後啟動正常 <version>選項卡中改動 <parent>     <groupId>org.springframework

Hbase異常windows 中使用hbase 異常java.io.IOException: Could not locate executable null\bin\winutils.exe

平時一般是在windows環境下進行開發,在windows 環境下操作hbase可能會出現異常(java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoo

異常java.lang.IllegalArgumentException: Control character in cookie value or attribute.

在服務器 jquery roc pro class leg val style mon 後臺提示: 嚴重: Error processing requestjava.lang.IllegalArgumentException: Control character in co

用eclipse部署tomcat時出現異常java.lang.IllegalArgumentException

prope valid 路徑 存在 exist ali eclips tom tex 用eclipse部署tomcat時出現異常:java.lang.IllegalArgumentException: Invalid ‘log4jConfigLocation‘ parame

JSP-匯入taglib 出現classNotFound異常java.lang.ClassNotFoundException: org.apache.taglibs.standard.tlv.Jst

案例 前端登入跳轉到指定jsp,報classNoFoundException,原因是頁面匯入 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 導致的 Caused by: java.lan

異常java.lang.NumberFormatException For input string""

由於DAO層部分引數是整形,所以在前端傳來資料的時候把傳來的資料轉成了整形 Integer a = Integer.parseInt(request.getParameter("a")); 由於定義的驗空函式裡的引數是String 在驗空函式裡又把a變數轉為了String型 在前端提交資料的

java空指標異常java.lang.NullPointException

一.什麼是java空指標異常     我們都知道java是沒有指標的,這裡說的"java指標"指的就是java的引用,我們不在這裡討論叫指標究竟合不合適,而只是針對這個異常本身進行分析。空指標就是空引用,java空指標異常就是引用本身為空,卻呼叫了方法,這個時候就會出現空指標異