equals() with BigDecimal

562 views
Skip to first unread message

Fabrizio Giudici

unread,
Apr 2, 2014, 7:52:39 PM4/2/14
to Project Lombok
Dear all,

if you have ever dealt with BigDecimal you should know that there's a
specific issue with equality that is well explained here:

http://stackoverflow.com/questions/6787142/bigdecimal-equals-versus-compareto

For BigDecimal itself, it makes sense. Now let's suppose I have a class
containing BigDecimal, such as the obvious

class Money
{
private BigDecimal amount;
private String currency;
}

As the designer of Money I could choose that Money equality is not so
strict, so this is the actual implementation of equals():

@Override
public boolean equals (final Object object)
{
if ((object == null) || (getClass() != object.getClass()))
{
return false;
}

final Money other = (Money)object;
return Objects.equals(this.currency, other.currency) &&
(this.amount.compareTo(other.amount) == 0);
}

Lombok's @EqualsAndHashcode always use a strict equals() comparison
between the two instances of amount. Do you think it would make sense to
have an option to the annotation that switch the implementation to
compareTo()? Note that hashcode() should be changed too from the usual
implementation, even though the change might not be trivial.

I'm not convinced of this - I'd equally welcome a "yes" answer (with
details on hashcode()), or a "no" answer with a reasonable rationale.

Thanks.

--
Fabrizio Giudici - Java Architect @ Tidalwave s.a.s.
"We make Java work. Everywhere."
http://tidalwave.it/fabrizio/blog - fabrizio...@tidalwave.it

Martin Grajcar

unread,
Apr 3, 2014, 2:16:47 AM4/3/14
to project...@googlegroups.com
I guess it makes sense, assuming that BigInteger does (which I rather doubt). A comment on hashCode:

There's a SO answer proposing using doubleValue().hashCode()
http://stackoverflow.com/a/14313302/581205. Given its crazy implementation http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/math/BigInteger.java#BigInteger.doubleValue%28%29 and the problems with overflow and precision loss, it might be better to go for toString() directly (which gets cached), normalize it somehow and hash.

Using unscaledValue() and scale() could be faster in cases when the "string normalization" is needed, but this would need some benchmarking (I volunteer to do if needed).
Reply all
Reply to author
Forward
0 new messages