排序阵列列表:比较方法违反了其一般合同



我正在尝试在Android应用程序中制作搜索自动完整功能。我正在将业务名称的列表以及我要列入一个ArrayList的列表业务类型,根据模糊搜索算法进行评分,然后根据搜索词根据分数对列表进行排序。我希望获得与业务名称相同的业务类型首先出现。我将商业和商业类型的实例在此类中进行评分,然后添加到列表,然后排序:

public class SearchMatch<T extends NameMatcher> implements Comparable<SearchMatch> {
    public T data;
    public int score;
    public SearchMatch(T data, int score) {
        this.data = data;
        this.score = score;
    }

    @Override
    public int compareTo(SearchMatch o) {
        if(this.score == o.score && this.data instanceof BusinessType 
            && o.data instanceof Business){
            return -1;
        }
        return o.score - this.score;
    }
}

...但这不起作用。我得到了"比较方法违反了其一般合同"。从collections.sort-- logcat中的其他内容。

我看不到它出了什么问题或它如何违反传递性(来自其他类似帖子)。奇怪的是,如果我返回1而不是-1,我没有遇到错误,但是我却偏爱的顺序错误。

谢谢

已解决

public class SearchMatch<T extends NameMatcher> implements      Comparable<SearchMatch> {
public final T data;
public final int score;
public SearchMatch(final T data,final  int score) {
    this.data = data;
    this.score = score;
}

@Override
public int compareTo(SearchMatch o) {
    if(this.score == o.score && this.data instanceof BusinessType 
        && o.data instanceof Business){
        return -1;
    }
    if(this.score == o.score && this.data instanceof Business 
        && o.data instanceof BusinessType){
        return 1;
    }
    return o.score - this.score;
}
}

考虑以下内容:

假设您有一个两个对象bbt具有相同的分数,一个是Business,另一个是BusinessType

compareTo(bt, b) -> -1
compareTo(b, bt) -> 0   // Incorrect!  This should be >= 0.

另一个潜在的问题是o.score - this.score不考虑整数溢出。

也有可能正在更改score和/或data的值,或者由于不正确的同步而导致的值不一致。我建议您声明这两个字段为final。这将使班级变得不可变,还将消除同步的需求(至少在这方面)。

(请参阅其他答案以解释您违反的"合同"。)

您违反了比较器Javadoc中发现的比较器的合同

sgn(比较(x,y))== -sgn(compare(y,x))

从本质上讲,您返回-1对于x和y的两个实例,以使if语句保留。这违反了界限合同。您应该尝试返回0或不应该发生异常。

这是可比的文档。它说明以下内容:

实施者必须确保sgn(x.compareto(y))== -sgn(y.compareto(x))用于所有X和Y。(这意味着x.compareto(y)必须抛出例外,如果y.compareto(x)抛出 例外。)

实施者还必须确保关系是传递的: (x.compareto(y)> 0&amp;&amp; y.compareto(z)> 0)含义x.compareto(z)> 0。

您的示例似乎并不满足这些警告。

最新更新