我有一個用Java編寫的JSON模式實現,它取決於Jackson(版本2.1.x)。出於準確性原因,我告訴傑克遜使用BigDecimal
作爲浮點數。「正常化」BigDecimal的哈希碼:howto?
對於JSON模式的需要,有一個特殊的需求:對於數值,JSON值的相等性是由它們的數學值相等來定義的。我需要這種檢查,因爲,舉例來說,這不是一個法律架構(在enum
值應該是唯一的):
{ "enum": [ 1, 1.0 ] }
但JsonNodes爲1
和1.0
是不相等的。因此,我編寫了番石榴的的實施方案,並在適當的地方使用Set<Equivalence.Wrapper<JsonNode>>
。這個實現應該適用於所有類型的節點,而不僅僅是數字節點。
實施這一項目的最困難的部分原來是doHash()
爲數字節點:/我需要等效數學值相同的hashCode,無論是整數或浮點數。
我能想出目前最好的是這樣的:
@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已經被覆蓋 - 請參閱編輯,我已經添加了一個鏈接到完整的實現 – fge
不清楚 - 是否有問題,代碼沒有返回相等的哈希碼相等的值,或者你錯誤地)試圖確保每一個獨特的值獨特的哈希碼? –
你想讓「1」,「1.0」,「1.00」返回相同的哈希碼嗎?也許你可以使用不使用hashCode的TreeSet? – zsxwing