【发布时间】:2013-01-14 02:33:22
【问题描述】:
我有一个用 Java 编写的 JSON Schema 实现,它依赖于 Jackson(版本 2.1.x)。出于准确性原因,我告诉 Jackson 使用 BigDecimal 表示浮点数。
对于JSON Schema的需求,有一个特殊的需求:JSON值相等,对于数值,是通过它们的数学值相等来定义的。我需要这种检查,例如,这不是一个合法的模式(enum 中的值应该是唯一的):
{ "enum": [ 1, 1.0 ] }
但是 1 和 1.0 的 JsonNodes 不相等。因此,我编写了 Guava 的Equivalence 的实现,并在适当的地方使用Set<Equivalence.Wrapper<JsonNode>>。而且这个实现应该适用于所有类型的节点,而不仅仅是数字节点。
这个实现中最困难的部分是doHash() 用于数字节点:/我需要相同的哈希码用于等效的数学值,无论它们是整数还是浮点数。
目前我能想到的最好的是:
@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)
【问题讨论】:
-
@zsxwing: doEquivalent 已经被覆盖——见编辑,我添加了一个完整实现的链接
-
不清楚 - 是否存在代码未针对相等值返回相等哈希码的问题,或者您是否(错误地)试图确保每个不同值的唯一哈希码?
-
您希望“1”、“1.0”、“1.00”返回相同的哈希码吗?也许您可以使用不使用 hashCode 的 TreeSet?
-
记住哈希码的关键规则:如果两个对象比较相等,则它们必须具有相同的哈希码。
-
@HotLicks 我知道...问题是我需要两个 数学等效 BigDecimals 相同的哈希码,当然我不能依赖
.equals()- - 我认为这个问题很清楚
标签: java guava hashcode bigdecimal