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

时间:2017-11-18 07:41:28

标签: java sorting comparison

我正在尝试对贷款的状态进行排序,其中贷款的状态为有效,已拒绝,待定和已批准。有效贷款应获得最高优先级,其他贷款应按任何顺序排列。我实施了比较器接口的比较()。

这是compare()

的实现
@Override
public int compare(Object o1, Object o2) {
    LoanAccountData loanAccountData1 = (LoanAccountData) o1;
    LoanAccountData loanAccountData2 = (LoanAccountData) o2;

    if (loanAccountData1.getStatusStringValue().equals("Active")) {
        return -1;
    } else {
        return 1;
    }
}

2 个答案:

答案 0 :(得分:2)

这里:

if (loanAccountData1.getStatusStringValue().equals("Active")) {
    return -1;

您永远不会与第二个对象进行比较 如果两个loanAccountData1.getStatusStringValue().equals("Active") 并且loanAccountData2.getStatusStringValue().equals("Active")是真的,你违反了对称原则,因为你应该返回0

使用Generic Comparator,您可以写:

public class LoanAccountDataComparatorByStatusActive implements Comparator<LoanAccountData> {

    @Override
    public int compare(LoanAccountData  o1, LoanAccountData o2) {    

        boolean isData1StatusActive = o1.getStatusStringValue().equals("Active");
        boolean isData2StatusActive = o2.getStatusStringValue().equals("Active");

        // if both status active, these have the same rank
        if (isData1StatusActive && isData2StatusActive){
           return 0;
        }

        if (isData1StatusActive){
           return -1;
        }

        if (isData2StatusActive){
           return 1;
        }
        // if no status active, these have the same rank
        return 0;
    }

}

请注意,它假定getStatusStringValue()永远不会返回null 否则在引用它之前添加所需的检查。

答案 1 :(得分:2)

根据compare的合同:here

您的代码违反了此规则:

  

实现者必须确保所有x和y的sgn(compare(x,y))== -sgn(compare(y,x))。 (这意味着当且仅当compare(y,x)抛出异常时,compare(x,y)必须抛出异常。)

如果x的状态有效且y的状态也有效,则compare(x, y)会说x较小,而compare(y, x) {1}}会说y更小。

我认为您要在此处执行的操作是将所有活动帐户排序到列表的开头。这意味着如果两个帐户都处于活动状态或两者都是其他帐户,则它们是相同的。如果一个帐户处于活动状态,则视为较小。

LoanAccountData loanAccountData1 = (LoanAccountData) o1;
LoanAccountData loanAccountData2 = (LoanAccountData) o2;
boolean o1Active = loanAccountData1.getStatusStringValue().equals("Active");
boolean o2Active = loanAccountData2.getStatusStringValue().equals("Active");
if (o1Active == o2Active) {
    return 0;
} else if (o1Active) {
    return -1;
} else {
    return 1;
}