Skip to content

Commit 9463a6e

Browse files
committed
JavaMoney/jsr354-ri/issues/146 Fixed hashCode/equals.
1 parent 0bec963 commit 9463a6e

File tree

1 file changed

+23
-8
lines changed

1 file changed

+23
-8
lines changed

src/test/java/javax/money/convert/DefaultExchangeRate.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import javax.money.NumberValue;
1515

1616
import java.io.Serializable;
17+
import java.math.BigDecimal;
1718
import java.util.ArrayList;
1819
import java.util.Arrays;
1920
import java.util.List;
@@ -252,7 +253,23 @@ public String toString() {
252253
*/
253254
@Override
254255
public int hashCode() {
255-
return Objects.hash(baseCurrency, conversionContext, factor, termCurrency, chain);
256+
// Numerically equal factors should produce the same hash code, so hash a normalized
257+
// version of the factor rather than the NumberValue object.
258+
BigDecimal normalizedFactor = factor.numberValue(BigDecimal.class).stripTrailingZeros();
259+
260+
// The exchange rate chain includes a reference to "this" if the caller doesn't explicitly
261+
// set a chain in the builder, so we can't naively hash the chain or we'll get infinite
262+
// recursion.
263+
int chainHash = 0;
264+
for (ExchangeRate chainedRate : chain) {
265+
if (chainedRate == this) {
266+
// Use a constant to represent the presence of this object in the chain.
267+
chainHash = Objects.hash(chainHash, "this");
268+
} else {
269+
chainHash = Objects.hash(chainHash, chainedRate);
270+
}
271+
}
272+
return Objects.hash(baseCurrency, conversionContext, normalizedFactor, termCurrency, chainHash);
256273
}
257274

258275
/*
@@ -265,13 +282,11 @@ public boolean equals(Object obj) {
265282
if (obj == this) {
266283
return true;
267284
}
268-
if (obj instanceof DefaultExchangeRate) {
269-
DefaultExchangeRate other = (DefaultExchangeRate) obj;
270-
return Objects.equals(baseCurrency, other.baseCurrency) &&
271-
Objects.equals(conversionContext, other.conversionContext) &&
272-
Objects.equals(factor, other.factor) && Objects.equals(termCurrency, other.termCurrency);
273-
}
274-
return false;
285+
DefaultExchangeRate other = (DefaultExchangeRate) obj;
286+
return Objects.equals(baseCurrency, other.baseCurrency) &&
287+
Objects.equals(conversionContext, other.conversionContext) &&
288+
factor.compareTo(other.factor) == 0 &&
289+
Objects.equals(termCurrency, other.termCurrency);
275290
}
276291

277292
/**

0 commit comments

Comments
 (0)