比较器导致 "Comparison method violates its general contract!" - 1300 项排序

Comperator caused "Comparison method violates its general contract!" - 1300 items sort

我有 1300 条数据,用我的计算机排序。当我使用 JAVA 6 时,排序工作正常。 当项目在 JAVA 7 上 运行 时,我收到此异常:

env: JAVA 7、Vaadin 6.8.12,用32位和64位测试都出现同样的错误。 (它在 JAVA 6 上工作正常)

Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeLo(TimSort.java:747)
    at java.util.TimSort.mergeAt(TimSort.java:483)
    at java.util.TimSort.mergeCollapse(TimSort.java:410)
    at java.util.TimSort.sort(TimSort.java:214)
    at java.util.TimSort.sort(TimSort.java:173)
    at java.util.Arrays.sort(Arrays.java:659)
    at java.util.Collections.sort(Collections.java:217)
    at com.vaadin.data.util.AbstractInMemoryContainer.doSort(AbstractInMemoryContainer.java:575)
    at com.vaadin.data.util.AbstractInMemoryContainer.sortContainer(AbstractInMemoryContainer.java:555)
    at com.vaadin.data.util.AbstractBeanContainer.sort(AbstractBeanContainer.java:440)
    at com.vaadin.ui.CustomTable.sort(CustomTable.java:4552)

这是我正在使用的比较器:

private class StudyRecordComparator implements Comparator<Object> {

    @Override
    public int compare(Object o1, Object o2) {
        if (o1 instanceof String && o2 instanceof String) {
            return ((String) o1).compareToIgnoreCase(((String) o2));
        }
        else if (o1 instanceof QuestionnaireStatusType && o2 instanceof QuestionnaireStatusType) {
            QuestionnaireStatusType status1 = (QuestionnaireStatusType) o1;
            QuestionnaireStatusType status2 = (QuestionnaireStatusType) o2;
            if(status1.equals(status2)) {
                return 0;
            }
            switch(status1) {
                case WAITING_FOR_REVIEW :
                    return -1;

                case IN_REVIEW :
                    if(status2.equals(QuestionnaireStatusType.WAITING_FOR_REVIEW)) {
                        return 1;
                    } else {
                        return -1;
                    }
                case WAITING_PUBLICATION :
                    if(status2.equals(QuestionnaireStatusType.WAITING_FOR_REVIEW) || status2.equals(QuestionnaireStatusType.IN_REVIEW)) {
                        return 1;
                    } else {
                        return -1;
                    }
                case PUBLISHED :
                    if(status2.equals(QuestionnaireStatusType.WITHDRAWN)) {
                        return -1;
                    } else {
                        return 11;
                    }
                case WITHDRAWN :
                    return 1;

            }
        }
        else if (o1 instanceof Date && o2 instanceof Date) {
            return ((Date) o1).compareTo(((Date) o2));
        } else if (o1 instanceof Integer && o2 instanceof Integer) {
            return ((Integer) o1).compareTo(((Integer) o2));
        } else if (o1 instanceof User && o2 instanceof User) {
            return ((User)o1).toString().compareToIgnoreCase(((User)o2).toString());
        }

        return 0;
    }

}

public enum QuestionnaireStatusType {

IN_PROGRESS("In progress"), 
WAITING_FOR_REVIEW("Waiting for review"),
IN_REVIEW("In review"),
WAITING_PUBLICATION("Waiting for publication"),
PUBLISHED("Published"),
WITHDRAWN("Withdrawn");

private final String field;

public String getField() {
    return field;
}

QuestionnaireStatusType(String field){
    this.field = field;
}

}

您的 collection 是否包含 null

如果是这样,则您的比较器存在一个问题:对于 null,它总是 returns 0,因此 null 被认为等于所有内容。

作为 A > B(前提)的结果,您还将有 A == nullnull == B 因此通过传递性 AB 也应该是相等,这违反了前提。

您需要为所有可能的值(包括 null 如果允许的话)建立一个完整且一致的顺序。

当您的 collection 包含混合类型(一些字符串、一些日期、一些 QuestionnaireStatusType)时,也会出现同样的问题。