java - "Normalizing"BigDecimal 的哈希码 : howto?

标签 java guava hashcode bigdecimal

我有一个用 Java 编写的 JSON Schema 实现,它依赖于 Jackson (版本 2.1.x)。出于准确性原因,我告诉 jackson 使用 BigDecimal用于 float 。

对于JSON Schema的需求,有一个特别的需求:JSON值的相等性,对于数值来说,是通过它们的数学值的相等性来定义的。我需要这种检查,因为,例如,这不是一个合法的模式(enum 中的值应该是唯一的):

{ "enum": [ 1, 1.0 ] }

但是 JsonNodes 为 11.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/

相关文章:

java - Guava 中的 ListenableFuture 将在哪个线程中调用 FutureCallback?

algorithm - 通过折叠然后除以素数来散列 key ?

来自多个字段的 Java hashCode

java - 具有 hashcode 函数的类

java - 如何使在一个 Servlet 中初始化的登录 session 在另一个 Servlet 中初始化且中间有 href 的登录 session 无效?

java - 为什么当我使用 "mvn -v"时我的电脑中有两个java路径

java - OkHttp 是否支持接受自签名 SSL 证书?

Java数组: how to insert delete items in array 1D and 2D

java - 在 Android 1.6 上使用 Google Guava

java - 用 Guava 修剪空格分隔的文件