我确实遇到了here所描述的问题。也就是说,当BigDecimal
等于被打破时,在类中使用这样的字段会阻止使用@EqualsAndHashCode
。我提出的唯一解决方案是exclude
这样的字段,但当然这不是最佳的。
有什么解决方案吗?有没有为字段/类型注入我自己的比较器?
答案 0 :(得分:0)
好吧,这不是龙目岛的错,因为目前尚不清楚如何比较BigDecimal
。无论如何,以下示例代码提供了一种解决方案:
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.math.BigDecimal;
@Data
@AllArgsConstructor
public class WithBigDecimals {
private int i;
private String s;
@EqualsAndHashCode.Exclude
private BigDecimal d;
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
@ToString.Exclude
private final BigDecimalComparer _bdc = new BigDecimalComparer();
private class BigDecimalComparer {
public WithBigDecimals getOuter() {
return WithBigDecimals.this;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof BigDecimalComparer))
return false;
BigDecimalComparer other = (BigDecimalComparer) obj;
double epsilon = d.doubleValue() / 1000d;
return d.doubleValue() - epsilon < other.getOuter().d.doubleValue() &&
other.getOuter().d.doubleValue() < d.doubleValue() + epsilon;
}
}
public static void main(String[] args) {
var a = new WithBigDecimals(42, "2.4", new BigDecimal("2.4"));
var b = new WithBigDecimals(42, "2.4", new BigDecimal("2.40"));
var c = new WithBigDecimals(42, "2.4", new BigDecimal(2.4));
System.out.printf("%s == %s ?? %b%n", a, b, a.equals(b));
System.out.printf("%s == %s ?? %b%n", b, c, b.equals(c));
System.out.printf("%s == %s ?? %b%n", a, c, a.equals(c));
}
}
如您所见,BigDecimal
被排除在@EqualsAndHashCode
中。为了重新注入它,我创建了另一个只能私下访问的字段。它在自动生成的equals()
方法中使用,可以随意提供比较。我在这里使用了一个几乎相等的简单版本。
答案 1 :(得分:0)
我最近遇到了同样的问题。
基本上,您会看到以下行为:
BigDecimal x = new BigDecimal("2");
BigDecimal y = new BigDecimal("2.00");
System.out.println(x.equals(y)); // False
System.out.println(x.compareTo(y) == 0 ? "true": "false"); // True
没有一个好的解决方案可以立即使用,但是您可以重新定义在hashCode和equals中使用的BigDecimal字段值:
@EqualsAndHashCode
class Test Class {
@EqualsAndHashCode.Exclude
private BigDecimal amount;
...
@EqualsAndHashCode.Include
private BigDecimal getAmountForEquals() {
return ofNullable(amount).map(BigDecimal::stripTrailingZeros).orElse(null);
}
}