18

Jackson(バージョン2.1.x)に依存するJavaで記述されたJSONスキーマ実装があります。精度の理由から、私はジャクソンにBigDecimal浮動小数点数に使用するように指示します。

JSONスキーマのニーズには、特にニーズがあります。数値の場合、JSON値の同等性は、それらの数学的値の同等性によって定義されます。たとえば、これは正当なスキーマではないため、この種のチェックが必要です(の値はenum一意である必要があります)。

{ "enum": [ 1, 1.0 ] }

しかし、とのJsonNodesは等しく1あり1.0ません。したがって、Guavaの同等性の実装をコーディングし、必要に応じて使用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

これは、現時点では、私が思いつくことができる最高のものです。

そのようなハッシュコードを計算するためのより良い方法はありますか?

編集:同等の実装の完全なコードはここにあります)

4

2 に答える 2

23

Doubleに変換し、DoubleのhashCodeを使用しますが、同等性はBigDecimalのcompareTo順序に基づいています。

数値的に同等の2つのBigDecimalsは、同じDoubleにマップされ、同じhashCodeを取得します。わずかに異なる一部のBigDecimal値は、二重丸めのために同じハッシュコードを取得しますが、ほとんどの異なる値は、必要なすべての異なるハッシュコードを取得します。

于 2013-01-14T04:19:54.013 に答える