Java 集合排序:排序列表时出现问题

Java Collection Sort: Issue while sorting list

这个问题已经被问过很多次,我的理解是 return 0 以及 1 和 -1,但我仍然遇到这个异常

java.lang.IllegalArgumentException: Comparison method violates its general contract!  
        at java.util.TimSort.mergeHi(TimSort.java:895)  
        at java.util.TimSort.mergeAt(TimSort.java:512)  
        at java.util.TimSort.mergeForceCollapse(TimSort.java:453)  
        at java.util.TimSort.sort(TimSort.java:250)  
        at java.util.Arrays.sort(Arrays.java:1512)  
        at java.util.ArrayList.sort(ArrayList.java:1454)  
        at java.util.Collections.sort(Collections.java:175)

代码片段

Collections.sort(List, new Comparator < Employee > () {
    public int compare(Employee emp1, Employee emp2) {
        int compareVal = 0;
        int returnVal = 0;
        try {
            if (emp1 == emp2) {
                returnVal = 0;
            } else {
                if (empName.equalsIgnoreCase(Constant.EMP_ID)) {
                    if (emp1.getEmpCode() != null && emp2.getEmpCode() != null) {
                        compareVal = emp1.getEmpCode().compareToIgnoreCase(emp2.getEmpCode());
                    }
                } else {
                    compareVal = 5;
                }

                if (compareVal > 0) {
                    returnVal = 1;
                } else if (compareVal < 0) {
                    returnVal = -1;
                } else if (compareVal == 0) {
                    returnVal = 0;
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnVal;
    }
});

也和JDK的版本有关。如果在JDK6做的不错,可能会出现你描述的JDK7中的问题,因为jdk7中的实现方法已经改变了。

看看这个:

说明:java.util.Arrays.sort 和 java.util.Collections.sort(间接)使用的排序算法已被替换。如果新的排序实现检测到违反 Comparable 协定的 Comparable,它可能会抛出 IllegalArgumentException。之前的实现默默忽略了这样的情况。如果需要以前的行为,您可以使用新系统 属性、java.util.Arrays.useLegacyMergeSort 来恢复以前的合并排序行为。

我不知道具体原因。但是,如果您在使用排序之前添加代码。会好的。

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

我尝试清理您的代码并向其中添加一些我自己的见解。看到您使用 Employee.getEmpCode() 作为排序基础,您可能应该使用 emp1.getEmpCode().equals(emp2.getEmpCode()) 而不是 emp1 == emp2。不确定你到底在做什么,但这会在没有局部变量的情况下完成你的函数所做的事情。

Collections.sort(List, new Comparator < Employee > () {
    public int compare(Employee emp1, Employee emp2) {
        try {
            if (emp1.getEmpCode().equals(emp2.getEmpCode()) {
                return 0;
            } else {
                if (empName.equalsIgnoreCase(Constant.EMP_ID)) {
                    if (emp1.getEmpCode() != null && emp2.getEmpCode() != null) {
                        return emp1.getEmpCode().compareToIgnoreCase(emp2.getEmpCode());
                    }
                } else {
                    return 1;
                }
                return 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});