为什么我得到"比较方法违反了它的一般合同"

时间:2014-03-31 17:32:30

标签: java comparator

如果我拨打这行代码

Arrays.sort(allNew, 0, sizeNew, mCatBPosComparator);

使用那个比较器

 private class BPosComparator implements Comparator<CatBPos> {

    private static final int SWAP_BPosS = 1;

    @Override
    public int compare(CatBPos p1, CatBPos p2) {
      int lCompare;

      if (TimeUtils.isNotVoid(p1.getHdopBPos().getTime()) && TimeUtils.isNotVoid(p2.getHdopBPos().getTime())) {
        lCompare = p1.getHdopBPos().getTime().compareTo(p2.getHdopBPos().getTime());
        if (lCompare != 0) {
          return lCompare;
        }
      }

      lCompare = p1.getBPos().getTime().compareTo(p2.getBPos().getTime());
      if (lCompare != 0) {
        return lCompare;
      }

      if (p1.getBPos().isDeparture() && p2.getBPos().isVacation()) {
        return SWAP_BPOS;
      } else if (p1.getBPos().isVacation() && p2.getBPos().isArrival()) {
        return SWAP_BPOS;
      }

      // Ankunft und Abfahrt für denselben Bahnhof sollen in der richtigen Reihenfolge sein
      if (p1.getBPos().isDeparture() && p2.getBPos().isArrival() && p1.getBPos().getStat().equals(p2.getBPos().getStat())) {
        return SWAP_BPOS;
      }

      return 0;
    }
  }

我遇到了这个例外:

Comparison method violates its general contract!

我看到很多关于此的话题。但我不明白。 你能帮帮我吗?

4 个答案:

答案 0 :(得分:4)

我怀疑这至少是一个直接的问题:

if (p1.getBPos().isDeparture() && p2.getBPos().isVacation()) {
    return SWAP_BPOS;
} else if (p1.getBPos().isVacation() && p2.getBPos().isDeparture()) {
    return SWAP_BPOS;
}

如果您拨打compare(p1, p2)然后compare(p2, p1),您将获得相同的非零结果...这会违反比较规则。

基本上,您的比较需要遵守documented rules。以上是一个问题 - 它完全有可能还有更多。您应该非常仔细地阅读规则,并考虑您的比较需要如何运作。

你可以在反向情况下否定SWAP_BPOS开始:

if (p1.getBPos().isDeparture() && p2.getBPos().isVacation()) {
    return SWAP_BPOS;
} else if (p1.getBPos().isVacation() && p2.getBPos().isDeparture()) {
    return -SWAP_BPOS;
}

这可能不是所有所必需的,但它是一个开始。

答案 1 :(得分:1)

您需要确保您的比较运算符遵循所有适当的数学规则:

  1. 如果A&lt; B和B&lt; C然后A&lt;下进行。
  2. 如果A&lt; B然后B>甲
  3. 如果A == B则B == A。
  4. 特别是,请注意可能为相反输入返回相同排序/结果的代码。您的比较需要能够明确订购您的商品。

    根据我的经验,第2点的错误似乎是最常见的错误。

答案 2 :(得分:0)

比较运算符需要是可传递的。简而言之,这意味着您应该以这样的方式定义它:如果a.compareTo(b)为负且b.compareTo(c)为负,则a.compareTo(c)也为负。这有点直观 - 如果a小于b且b小于c,则a也小于c。此外,您应该确保a.compareTo(b)为零时,b.compareTo(a)为零,即如果a等于b,则b等于a。

答案 3 :(得分:0)

基本上,您的比较方法需要保持一致。如果A> B和B> C,那么A必须大于C.你的代码可能在那里失败。