1

我很想对一个项目数组进行排序,如果一个项目的 id 等于所选项目的 id(也属于该数组),则该项目应该被带到数组的开头。其余元素的排序顺序是它们与给定位置的距离。

java.lang.IllegalArgumentException: Comparison method violates its general contract!在自定义比较器中遇到了可怕的异常,实现如下:

Location location = ...; // may be null
Item selectedItem = ...; // may be null or an element of the array to be sorted

private final Comparator<Item> comparator = new Comparator<Item>() {
    @Override
    public int compare(Item p1, Item p2) {
        // if p1 is the currently selected item, bring p1 to the top
        // if p2 is the currently selected item, bring p2 to the top
        // else sort p1 and p2 by their distance from location
        if (selectedItem != null) {
            if (selectedItem.getId() == p1.getId()) { //id's are int and unique in the array
                return -1;
            } else if (selectedItem.getId() == p2.getId()) {
                return 1;
            }
        }

        if (location != null) { //location is an Android Location class instance
            Float distance1 = location.distanceTo(p1.getLocation());
            Float distance2 = location.distanceTo(p2.getLocation());
            return distance1.compareTo(distance2);
        } else {
            return 0;
        }
    }
};

我没有复制问题的确切顺序,但是到目前为止,所有对错误的观察都发生在selectedItem并且location不为空(它们可能都为空)时。

有什么提示吗?

谢谢

4

2 回答 2

1

我相信您的问题在于,当等于 时selectedItem,当被比较的两个元素相等时,您不会返回 0。这样,比较xyx更大,但比较yx更大y(假设xy都等于selectedItem)。这不可能。

if (p1.getId() == p2.getId()) return 0;
于 2013-05-15T20:37:12.870 回答
0

我认为在这个问题的答案中可以找到提示:https ://stackoverflow.com/a/8327575/338479

比较器有规则(“合同”)。一个是对象总是比较等于自己(compare()返回 0)。另一个是如果 A>B 且 B>C,则 A>C。另一个是 B>A 返回 A>B 的相反结果。

我在您的比较器中没有看到任何明显违反这些规则的行为,但我不知道您的其他代码的内部工作原理。是否存在您的distanceTo()方法可能违反本合同规则的情况?

位置selectedItem是否有可能在排序过程中发生变化?

于 2013-05-15T22:00:02.123 回答