1

在一个 android 应用程序中,我有一个位置列表。我需要根据它们与用户位置的距离对它们进行排序。为此,我实现了一个自定义比较器:

Collections.sort(houseList, new Comparator<HouseEntity>()
  {
     @Override
     public int compare(HouseEntity house1, HouseEntity house2)
     {
        if(userLocation == null) return 0;
        return (int) (userLocation.distanceTo(house1.location) - userLocation.distanceTo(house2.location));
     }
  });

它在我所做的所有测试中运行良好。但是,一些用户因以下错误而崩溃:

java.lang.IllegalArgumentException: Comparison method violates its general contract!

在阅读了关于 SO 的所有其他相同问题后,我得出结论,当逻辑中可能存在错误时会出现此错误(例如,我们可能同时得到 a>b 和 b>a)。但我找不到任何场景来复制该逻辑错误。

什么情况可能导致此错误?我该如何解决?

非常感谢您的帮助

4

2 回答 2

1

正如Peter Lawrey所说,您应该使用Double.compare(x, y)orFloat.compare(x, y)而不是强制转换为 int。这里的解释:

比较器必须是可传递的,即只要 A == B 和 B == C,那么 A == C 也是如此。假设我们有三个点AB并且C到用户位置的距离为 0.2、0.4 和 1.3。

  1. (int) (0.2 - 0.4) = (int) (-0.2) = 0 =>A == B
  2. (int) (0.4 - 1.3) = (int) (-0.9) = 0 =>B == C
  3. (int) (0.2 - 1.3) = (int) (-1.1) = -1 =>A < C

如您所见,比较器不是传递的。

于 2013-01-18T12:46:19.440 回答
0

如果userLocation == null那么house1.equals(house2)应该给真。

于 2013-01-18T11:44:32.297 回答