[
https://issues.apache.org/jira/browse/LANG-1113?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14561092#comment-14561092
]
Bernd commented on LANG-1113:
-----------------------------
Hello Benedikt,
i do not have so much insight of commons-lang and related classes that i would
say i could easily provide a good API.
I also have no clue how to really get correct hash-code for this case.
But i can post how we workaround this problem in our pojo (pseudo-code).
{code:title=XYZPojo.java|borderStyle=solid}
@Override
public boolean equals(final Object obj) {
final EqualsBuilder builder = new EqualsBuilder();
for (PojoField pojoField : allFieldsOfPojo) {
try {
final Method fieldGetter = pojoField.getGetter();
final Object left = fieldGetter.invoke(this, new Object[0]);
final Object right = fieldGetter.invoke(obj, new Object[0]);
final Class<?> type = pojoField.getField().getType();
if ((left == null && right != null) || (left != null && right
== null)) {
// Unbalanced null case
return false;
} else if (left != null &&
type.isAssignableFrom(BigDecimal.class)) {
// BigDecimal case
if (((BigDecimal) left).compareTo((BigDecimal) right) != 0)
{
return false;
}
} else if (left != null &&
type.isAssignableFrom(ZonedDateTime.class)) {
// ZonedDateTime case
if (!((ZonedDateTime) left).isEqual((ZonedDateTime) right))
{
return false;
}
} else {
// Default case
builder.append(left, right);
}
} catch (IllegalArgumentException | IllegalAccessException |
InvocationTargetException e) {
throw new RuntimeException(e);
}
}
return builder.isEquals();
}
...
@Override
public int hashCode() {
final HashCodeBuilder builder = new HashCodeBuilder();
for (PojoField pojoField : allFieldsOfPojo) {
try {
final Method fieldGetter = pojoField.getGetter();
final Object obj = fieldGetter.invoke(this, new Object[0]);
final Class<?> type = pojoField.getField().getType();
if (obj != null && type.isAssignableFrom(BigDecimal.class)) {
// Reduce BigDecimal to Double to get a hash code dependent
on the numeric value
builder.append(((BigDecimal) obj).doubleValue());
} else {
builder.append(obj);
}
} catch (IllegalArgumentException | IllegalAccessException |
InvocationTargetException e) {
throw new RuntimeException(e);
}
}
return builder.toHashCode();
}
{code}
> Manages Comparable in EqualsBuilder
> -----------------------------------
>
> Key: LANG-1113
> URL: https://issues.apache.org/jira/browse/LANG-1113
> Project: Commons Lang
> Issue Type: New Feature
> Components: lang.builder.*
> Reporter: Simon Meyffret
> Priority: Trivial
> Labels: BigDecimal, EqualsBuilder
> Fix For: Discussion
>
>
> As explained by LANG-393 and LANG-467, {{EqualsBuilder}} fails to provide a
> proper way to handle {{BigDecimal}} since {{BigDecimal}} takes the scale into
> account when using {{equals()}} but not with {{compareTo()}}.
> Would it be possible to add a method *{{appendComparable()}}* in
> {{EqualsBuilder}} to manages {{Comparable}} objects when we want to build
> equality on {{compareTo()}} and not {{equals()}}?
> Making clear that {{EqualsBuilder}} is not compliant with {{HashCodeBuilder}}
> when using this method.
> For example:
> {code:borderStyle=solid}
> return new EqualsBuilder()
> .append(this.name, other.name)
> .appendComparable(this.amount, other.amount)
> .isEqual();
> {code}
> with:
> {code:title=EqualsBuilder.java|borderStyle=solid}
> /**
> * <p>Test if two <code>Comparable</code>s are equal using their
> * <code>compareTo</code> method.</p>
> * <p>This may break the <code>equals</code>/<code>hashcode</code>
> contract but
> * it is useful in some situation, specially with {@link
> java.math.BigDecimal}.</p>
> *
> * @param lhs the left hand comparable
> * @param rhs the right hand comparable
> * @return EqualsBuilder - used to chain calls.
> */
> public <T extends Comparable<? super T>> EqualsBuilder
> appendComparable(T lhs, T rhs) {
> if (isEquals == false) {
> return this;
> }
> if (lhs == rhs) {
> return this;
> }
> if (lhs == null || rhs == null) {
> isEquals = false;
> return this;
> } else if (lhs.compareTo(rhs) != 0) {
> isEquals = false;
> return this;
> }
> return this;
> }
>
> /**
> * <p>Performs a deep comparison of two <code>Comparable</code>
> arrays.</p>
> *
> * @param lhs the left hand <code>Comparable[]</code>
> * @param rhs the right hand <code>Comparable[]</code>
> * @return EqualsBuilder - used to chain calls.
> * @see #appendComparable(Comparable, Comparable)
> */
> public <T extends Comparable<? super T>> EqualsBuilder
> appendComparable(T[] lhs, T[] rhs) {
> if (isEquals == false) {
> return this;
> }
> if (lhs == rhs) {
> return this;
> }
> if (lhs == null || rhs == null) {
> isEquals = false;
> return this;
> }
> if (lhs.length != rhs.length) {
> isEquals = false;
> return this;
> }
> for (int i = 0; i < lhs.length && isEquals; ++i) {
> appendComparable(lhs[i], rhs[i]);
> }
> return this;
> }
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)