我正在尝试在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;
}
}
考虑以下内容:
假设您有一个两个对象b
和bt
具有相同的分数,一个是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。
您的示例似乎并不满足这些警告。