比较方法违反了其一般合同和方法比较

时间:2014-10-13 09:43:22

标签: java comparison compare comparator compareto

我的课程Contact包含字段firstNamelastNameemails。我需要使用Collection.sort(...)对它们进行排序,但我有一个例外:

  

java.lang.IllegalArgumentException:比较方法违反了其一般合同!

我的compareTo方法:

    @Override
public int compareTo(Contact another) {
    int compareFirstName = 0;
    if (this.getFirstName() != null && another.getFirstName() != null) {
        compareFirstName = this.getFirstName().compareToIgnoreCase(
                another.getFirstName());

        if (compareFirstName == 0) {
            int compareLastName = 0;
            if (this.getLastName() != null && another.getLastName() != null) {
                compareLastName = this.getLastName().compareToIgnoreCase(
                        another.getLastName());

                if (compareLastName == 0) {
                    int compareEmail = 0;
                    if (this.getEmails() != null
                            && another.getEmails() != null) {
                        compareEmail = this.getEmails()
                                .compareToIgnoreCase(another.getEmails());

                        return compareEmail;
                    } else {

                        return 0;
                    }
                } else {
                    return compareLastName;
                }
            } else {
                int compareEmail = 0;
                if (this.getEmails() != null && another.getEmails() != null) {
                    compareEmail = this.getEmails().compareToIgnoreCase(
                            another.getEmails());

                    return compareEmail;
                } else {

                    return 0;
                }
            }
        } else {

            return compareFirstName;
        }
    } else {
        int compareLastName = 0;
        if (this.getLastName() != null && another.getLastName() != null) {
            compareLastName = this.getLastName().compareToIgnoreCase(
                    another.getLastName());

            if (compareLastName == 0) {
                int compareEmail = 0;
                if (this.getEmails() != null && another.getEmails() != null) {
                    compareEmail = this.getEmails().compareToIgnoreCase(
                            another.getEmails());

                    return compareEmail;
                } else {

                    return 0;
                }
            } else {

                return compareLastName;
            }
        } else {
            int compareEmail = 0;
            if (this.getEmails() != null && another.getEmails() != null) {
                compareEmail = this.getEmails().compareToIgnoreCase(
                        another.getEmails());

                return compareEmail;
            } else {

                return 0;
            }
        }
    }
}

请帮我在compareTo方法中找到错误。感谢。

1 个答案:

答案 0 :(得分:3)

您的实施确实违反了合同。

假设您有3个联系人:

contact1 : First Name = "John", Last Name = "Doe", Email = "x@gmail.com"
contact2 : First Name = "John", Last Name = "Doe", Email = null
contact3 : First Name = "John", Last Name = null, Email = "y@gmail.com"

根据您的逻辑:

contact1.compareTo(contact2)返回0(因为它们具有相同的名字和姓氏) contact2.compareTo(contact3)也返回0(因为你只按名字比较) 但是contact1.compareTo(contact3)不会返回0(因为他们有不同的电子邮件)。

compareTo必须是及时的。

解决此问题的方法是不要忽略仅在您要比较的其中一个联系人中为null的属性。例如,如果this.getLastName()== null&& another.getLastName()!= null,返回1(假设您要在非空姓后命名null个姓)。