Ho un'implementazione JSON Schema scritta in Java che dipende da Jackson (versione 2.1.x). Per ragioni di precisione, dico a Jackson di usare BigDecimal
per i numeri in virgola mobile."Normalizzazione" del codice hash di BigDecimal: howto?
Per le esigenze dello schema JSON, vi è una particolare esigenza: l'uguaglianza del valore JSON, per i valori numerici, è definita dall'uguaglianza del loro valore matematico. Ho bisogno di questo tipo di controllo dal momento che, per esempio, non si tratta di uno schema legale (valori in un enum
dovrebbe essere unico):
{ "enum": [ 1, 1.0 ] }
Ma JsonNodes per 1
e 1.0
non sono uguali. Pertanto, ho codificato un'implementazione di Guava Equivalence, e utilizzare Set<Equivalence.Wrapper<JsonNode>>
dove appropriato. E questa implementazione dovrebbe funzionare per tutti i tipi di nodi, non solo per i nodi numerici.
E la parte più difficile di questa implementazione risulta essere doHash()
per nodi numerici:/Ho bisogno lo stesso codice hash per valori matematici equivalenti, che siano numeri interi o numeri in virgola mobile.
il meglio che potevo venire con al momento è questa:
@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
Questo è, al momento, il meglio che ho potuto trovare.
Esiste un modo migliore per calcolare un codice hash di questo tipo?
(edit: in pieno il codice della realizzazione Equivalenza here)
@zsxwing: doEquivalent è già scaduto - vedi modifica, ho aggiunto un collegamento all'implementazione completa – fge
Non chiaro - c'è un problema che il codice non restituisce uguali codici hash per valori uguali, oppure sei tu (erroneamente) cercando di assicurare un codice hash univoco per ogni valore distinto? –
Vuoi che "1", "1.0", "1.00" restituiscano lo stesso codice hash? Forse puoi usare TreeSet che non usa hashCode? – zsxwing