等于并与BigDecimal进行比较

时间:2019-09-16 21:38:44

标签: java

我有一个覆盖hashCode(equals()方法的类。在处理BigDecimal时,我必须使用compareTo()而不是Objects.equals()

public class MyProduct extends Product{

private BigDecimal price;


@Override
public int hashCode() {
    return Objects.hash(price);
}


@Override
public boolean equals(Object obj) {

        if (this == obj) return true; // is this right or should this be deleted

        if (obj == null || getClass() != obj.getClass()) return false;

        final Product other = (Product) obj;

        // is this right?
        if (price == null ? (other.price != null) : price.compareTo(other.price) != 0) {
            return false;
        }
        return super.equals(obj);
    }

}

我有以下问题:

  1. 是否应该从if (this == obj) return true;方法中删除行equals()?因为在这一行中,compareTo不会被触发并且可以计算出错误的equals(),对吗?
  2. 是否可以改善equals()方法?

3 个答案:

答案 0 :(得分:1)

第一行只是一个优化,旨在在两个引用都指向同一对象时尽早返回结果。

price是否可以为空?我认为是这样,因为您正在equals()实现中对其进行检查。在这种情况下,如果other.pricenull,则您的代码将无法工作。具体代码如下:

price.compareTo(other.price) != 0

会抛出一个NullPointerException

您可以这样解决它:

    @Override
    public boolean equals(Object obj) {

        if (this == obj) return true; // is this right or should this be deleted

        if (obj == null || getClass() != obj.getClass()) return false;

        final MyProduct other = (MyProduct) obj;

        // If you prefer, the below two can be replaced with a single condition
        // price != null ^ other.price != null
        // Credits to @Andreas
        if (price == null && other.price != null) {
            return false;
        }
        if (price != null && other.price == null) {
            return false;
        }
        if (other.price != null && price.compareTo(other.price) != 0) {
            return false;
        }

        return super.equals(obj);
    }

现在,您可以将它缩短一些,但就我个人而言,这种方式最易读。

无论如何,除非您真的非常在乎自定义equals()实现,否则我建议您使用IDE生成一个并坚持使用。他们大多数时候的表现不错,您不必担心会被打破(尽管比较BigDecimals对他们来说可能很棘手,因为您不在乎规模,而只是在乎价值)

答案 1 :(得分:0)

我写了一个非常实用的方法,可以用来比较两个BigDecimal,而不会抛出NPE:

// returns true, if val1 is the same as val2
// can this be improved ?
public static boolean isEqual(BigDecimal val1, BigDecimal val2) {
        return !((val1 != null ^ val2 != null) || (val2 != null && val1.compareTo(val2) != 0));
    }

这可以在equals-method中使用:

@Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        final MyProduct other = (MyProduct) obj;

        if(!isEqual(price, other.price)) return false;

        return super.equals(obj);
    }

答案 2 :(得分:0)

我找到了最简单的方法:

public static boolean isEqual(BigDecimal val1, BigDecimal val2) {
    return val1 != null ^ val2 != null && val2 != null && val1.compareTo(val2) != 0;
}

,然后在equals()中使用它:

public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        final MyProduct other = (MyProduct) obj;

        if(!isEqual(price, other.price)) return false;

        return super.equals(obj);
    }