Avvertenze sull'uso di String.hashCode () su un interruttore su java 1.7

1

Ci sono diversi casi in cui voglio passare l'input di una stringa. Ho deciso di implementare qualcosa del tipo:

public Object doStuff(String param) {
    switch (param.hashCode()) {
    case 1234546:
         break;
    case -18754956:
         break;
    default:
         whatever();
    }
}

Funziona come previsto, ma c'è questa sensazione che qualcosa può andare storto.

Quali sono le possibili insidie nell'usare questa implementazione? Sono obbligato ad usare java 1.5 o 1.6 perché dettami aziendali così (quindi non posso aggiornare a 1.7 o successive).

Esiste una migliore implementazione di uno switch su Strings diverso da una catena mostruosa di if-then-else (ai fini di questa domanda, supponiamo di non poter fare if-then-else su ogni possibile valore di stringa dell'input)?

related: Qual è il vantaggio dell'attivazione di String in Java 7? , ma sto chiedendo il pre-1.7

    
posta Mindwin 23.02.2015 - 17:03
fonte

2 risposte

3

I codici hash non sono unici. Esistono numerose stringhe che includono, ad esempio, 1234546 . Se vuoi verificare la stringa "foo" e la stringa% non correlata, senza significato,% co_de ha lo stesso hash, il tuo codice tratterà falsamente "bar" come "bar" invece di rifiutarlo / passare a "foo" .

La risoluzione è generalmente possibile (controlla se il valore è effettivamente default della stringa desiderata in ogni caso), ma è piuttosto un po 'di codice extra, specialmente se c'è un caso equals (dato che devi trasferire il controllo fuori dal caso "sbagliato" e al caso predefinito). È così che lo switch-over-string proposta di funzionalità lo desabora. Non è carino.

I codici hash non sono significativi. Qualcuno deve scoprire il codice hash e hard-code, e il codice ha più numeri magici senza senso. Puoi e dovresti scrivere la stringa in un commento accanto al valore letterale intero, ma è comunque un onere di manutenzione.

Tecnicamente, l'algoritmo hash potrebbe cambiare anche quando la JVM viene aggiornata o quando l'ambiente di distribuzione è cambiato, ecc. - a seconda della JVM, forse anche quando la JVM viene riavviata! E poi il codice sarebbe silenziosamente sbagliato. Questo probabilmente non accadrà realmente (penso che l'implementazione di switch-over-string di Java 7 dipenda dal fatto che il compilatore è in grado di predire il valore default dei letterali stringa).

    
risposta data 23.02.2015 - 17:18
fonte
3

Quando confronti due stringhe usando i loro codici hash:

  • Se due codici hash sono diversi, significa che le stringhe sono diverse,

  • Se due codici hash sono identici, questo non significa nulla. Le stringhe originali possono essere identiche o diverse.

Allo stesso modo, una lunghezza di stringa diversa indica che due stringhe sono diverse, ma se hai la stessa lunghezza, non significa che due stringhe siano uguali.

Questo è il motivo per cui se è necessario eseguire un'azione in base all'input dell'utente, dovrebbe utilizzare la stringa originale, non il suo codice hash. Avere un switch basato sulla stringa stessa è un modo per andare. Un'altra alternativa da prendere in considerazione è una mappa .

Il vantaggio di una mappa è che è possibile modificarlo in fase di esecuzione, ad esempio definendo i diversi input e le azioni corrispondenti in un file di configurazione. Questo può anche essere utile se passi a stringhe lunghe che sarebbero strane codificate in un'istruzione switch.

    
risposta data 23.02.2015 - 17:17
fonte

Leggi altre domande sui tag