2013-03-28 11 views
5

Ho chiesto similar question per il metodo string.GetHashCode() in .NET. Tratto da allora, ho imparato che non possiamo fare affidamento sull'implementazione implicita del codice hash per i tipi di buit-in, se vogliamo usarlo su macchine diverse. Pertanto, presumo che l'implementazione Java di String.hashCode() sia anche instabile tra diverse configurazioni hardware e possa comportarsi in modo diverso su VM (non dimenticare le diverse implementazioni VM)Stabilità Java e string.hashCode() su macchine nel cluster

Attualmente stiamo discutendo un modo per trasformare in modo sicuro una stringa in un numero in Java, mediante hashing, ma l'algoritmo hash deve essere stabile tra diversi nodi di un cluster ed essere veloce da valutare, poiché ci sarà un'alta frequenza di utilizzo. I miei compagni di squadra insistono sul metodo nativo hashCode e avrò bisogno di alcuni argomenti ragionevoli per convincerli a riconsiderare un altro approccio. Attualmente, posso solo pensare alle differenze tra le configurazioni della macchina (x86 e x64), possibilmente diversi venditori della JVM su alcune macchine (difficilmente applicabile nel nostro caso) e differenze nell'ordine dei byte, a seconda della macchina che l'algoritmo sta correre. Naturalmente, la codifica dei caratteri è probabilmente da considerare.

Mentre tutte queste cose mi vengono in mente, non sono sicuro al 100% in nessuna di esse di essere una ragione abbastanza forte, e apprezzerei la vostra esperienza ed esperienza in questo settore. Questo mi aiuterà a costruire argomenti più forti per favorire la scrittura di un algoritmo di hashing personalizzato. Inoltre, gradirò i consigli su cosa non fare quando lo si implementa.

+1

Il codice hash della stringa è ben definito e uguale su qualsiasi piattaforma Java. – ZhongYu

+1

http://stackoverflow.com/questions/785091/consistency-of-hashcode-on-a-java-string – zch

+0

@ zhong.j.yu stai assumendo [JRockit] (http://www.oracle.com /technetwork/middleware/jrockit/overview/index.html) e [IBM JVM] (http://publib.boulder.ibm.it/infocenter/java7sdk/v7r0/index.jsp? topic =% 2Fcom.ibm.java.lnx.70.doc% 2Fuser% 2Fjava_jvm.html) hanno la stessa implementazione per 'String # hashCode'. –

risposta

11

L'attuazione di String.hashCode() è specified nella documentazione, quindi è garantito per essere coerenti:

il codice hash per un oggetto String è calcolata come

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] 

utilizzando int aritmetica, dove s [i] è il carattere ith della stringa, n è la lunghezza della stringa e^indica l'esponenziazione. (Il valore hash della stringa vuota è zero.)

Tutte queste operazioni sono implementate in modo indipendente dalla piattaforma per Java, ad esempio l'ordine dei byte della piattaforma è irrilevante.

Detto questo, modi di di ottenere a String possono essere complicati, se lo si ottiene da un file o da un'altra fonte di byte. In tal caso, stai bene fino a quando specifichi esplicitamente un Charset. (Ricordate che String s non hanno differenti codifiche di per sé, una codifica è una specifica per conversioni tra un byte[] e String.)

+0

Per quanto riguarda le specifiche (e componenti java di base che conosco DO), in realtà sembra abbastanza sicuro. Grazie –

3

si può guardare il sourcecode, also shown below. Da quello che posso vedere (dopo tutti i 10 secondi di analisi) questo dovrebbe essere stabile su macchine e architetture. E Louis lo conferma citando una specifica, ancora meglio se si crede alle specifiche. :-)

Tuttavia, questo potrebbe variare se un JRE diverso sceglie di implementarlo in modo diverso e violare le specifiche.

public int hashCode() { 
    int h = hash; 
    if (h == 0) { 
     int off = offset; 
     char val[] = value; 
     int len = count; 

     for (int i = 0; i < len; i++) { 
      h = 31*h + val[off++]; 
     } 

     hash = h; 
    } 

    return h; 
} 
+0

Grazie per la risposta. Ho esaminato personalmente il codice sorgente e non ho trovato nulla che potesse essere un problema. Tuttavia, qualcosa mi dice che questo non è l'unico posto dove le cose possono andare storte. Speriamo che diverse JVM (diversi fornitori) nello stesso cluster non siano un caso per noi. –

+1

Penso che se un fornitore sta rompendo le specifiche potresti eseguire un gruppo di stringhe conosciute e confrontarle con i risultati ufficiali. Assicurati di eseguire alcuni _long_ ones. Nei primi tempi di Java, il metodo hashCode considerava solo i primi 16 (forse 32?) Caratteri. Potevo vedere un venditore che cercava di vincere un benchmark facendo qualcosa di simile. – user949300

+0

Buon consiglio, grazie per averlo condiviso. Credo che per la questione attuale ci atteniamo alla JVM di Oracle, anche se quella conoscenza potrebbe rivelarsi abbastanza utile un giorno. Avere pensieri su di esso, un tale "guadagno in termini di prestazioni" può costare un sacco di comportamenti indesiderati e imprevedibili. Mi chiedo se un venditore di JVM là fuori possa cadere in quella categoria –