我有一个用 Java 编写的 JSON Schema 实现,它依赖于 Jackson (版本 2.1.x)。出于准确性原因,我告诉 jackson 使用 BigDecimal
用于 float 。
对于JSON Schema的需求,有一个特别的需求:JSON值的相等性,对于数值来说,是通过它们的数学值的相等性来定义的。我需要这种检查,因为,例如,这不是一个合法的模式(enum
中的值应该是唯一的):
{ "enum": [ 1, 1.0 ] }
但是 JsonNodes 为 1
和 1.0
不相等。因此,我编写了 Guava 的 Equivalence 的实现。 ,并使用 Set<Equivalence.Wrapper<JsonNode>>
在适当情况下。而且这个实现应该适用于所有类型的节点,而不仅仅是数字节点。
这个实现中最困难的部分是 doHash()
对于数字节点:/我需要相同的哈希码来表示等效的数学值,无论它们是整数还是 float 。
目前我能想到的最好的是:
@Override
protected int doHash(final JsonNode t)
{
/*
* If this is a numeric node, we want a unique hashcode for all possible
* number nodes.
*/
if (t.isNumber()) {
final BigDecimal decimal = t.decimalValue();
try {
return decimal.toBigIntegerExact().hashCode();
} catch (ArithmeticException ignored) {
return decimal.stripTrailingZeros().hashCode();
}
}
// etc etc -- the rest works fine
目前,这是我能想到的最好的办法。
有没有更好的方法来计算这样的哈希码?
(编辑:等效实现的完整代码 here )
最佳答案
转换为 Double 并使用 Double 的 hashCode,但基于 BigDecimal compareTo 顺序的相等性。
两个数值相等的 BigDecimals 将映射到相同的 Double,并得到相同的 hashCode。由于双舍入,一些略有不同的 BigDecimal 值将获得相同的哈希码,但大多数不同的值将获得不同的哈希码,这就是您所需要的。
关于java - "Normalizing"BigDecimal 的哈希码 : howto?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14311644/