你如何干净地实现compareTo方法?

时间:2012-01-15 19:12:22

标签: java comparable

目前我正在以下列形式编写二次函数的compareTo方法:ax ^ 2 + bx + c。

a,b,c是通过构造函数传递给类的整数系数。

在compareTo方法中,我应该首先比较两个函数之间的a系数,但如果它们相等,我会比较b系数。如果b是相等的,我比较c。

我为此提出的方法最终变得相当丑陋:

public int compareTo(QuadraticFunction other)
{
    if (a > other.a)
        return 1;
    else if (a < other.a)
        return -1;
    else if (b > other.b)
        return 1;
    else if (b < other.b)
        return -1;
    else if (c > other.c)
        return 1;
    else if (c < other.c)
        return -1;
    else
        return 0;
}

所以我想知道,如果你有这些“分层”的比较系统(比如在c之前比较a之前的b),那么实现它们的最佳方法是什么?如果你不得不经历10多个变量,我无法想象像我一样编写一种方法。

4 个答案:

答案 0 :(得分:6)

对于任意数量的系数(所有相同类型),您应该将它们存储在List(或类似的东西)中,而不是单独命名的成员变量。这允许您将示例代码转换为迭代。

答案 1 :(得分:2)

Guava Libraries提供了一个非常好的工具,名为ComparisonChain

您的代码看起来像这样:

import com.google.common.base.ComparisonChain;
...
public int compareTo(QuadraticFunction other) {
  return ComparisonChain.start()
    .compare(a, other.a)
    .compare(b, other.b)
    .compare(c, other.c)
    .result();
}

答案 2 :(得分:1)

为了便于阅读,并使用a,b,c的内置比较方法,我会重构:

public int compareTo(QuadraticFunction other) {
    if (a.equals(other.a)) {
        if (b.equals(other.b))
            return c.compareTo(other.c);
        return b.comapreTo(other.b);
    }
    return a.compareTo(other.a);
}

此代码假定字段为Number。如果它们是基元,则将它们转换为包裹类型或更改a.equals(b) to a == b and change a.compareTo(b)to a - b`。

另请注意,当if返回时,永远不需要else - 这是多余的,因此请将其删除。

答案 3 :(得分:0)

您可以使用如下所示的成语,将比较分为按字段清除的部分,每个字段只需要一次测试,并使用signum方法生成返回值。

注意,下面的减法适用于intshortcharbyte字段。 对于longfloatdouble字段,您必须对<==使用单独的检查,以避免溢出/下溢,并且由于四舍五入。比较浮点值时要小心NaN。 对于Comparable字段,您可以在使用单独的条件处理compareTo之后将delta设置为null的结果。

long delta = ((long) a.field1) - b.field1;
if (delta != 0) { return Long.signum(delta); }

delta = ((long) a.field2) - b.field2;
if (delta != 0) { return Long.signum(delta); }

...

return 0;