Der hashCode-Wert eines Java- Strings wird wie folgt berechnet: ( String.hashCode () ):
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
Gibt es Umstände (z. B. JVM-Version, Anbieter usw.), unter denen der folgende Ausdruck als falsch ausgewertet wird?
boolean expression = "This is a Java string".hashCode() == 586653468
Update Nr. 1: Wenn Sie behaupten, dass die Antwort "Ja, es gibt solche Umstände" lautet, geben Sie bitte ein konkretes Beispiel dafür, wann "Dies ist eine Java-Zeichenfolge" .hashCode ()! = 586653468. Versuchen Sie, so spezifisch / konkret zu sein wie möglich.
Update Nr. 2: Wir alle wissen, dass es im Allgemeinen schlecht ist, sich auf die Implementierungsdetails von hashCode () zu verlassen. Ich spreche jedoch speziell über String.hashCode (). Bitte konzentrieren Sie die Antwort auf String.hashCode (). Object.hashCode () ist im Kontext dieser Frage völlig irrelevant.
Antworten:
Ich kann diese Dokumentation bereits in Java 1.2 sehen.
Zwar sollten Sie sich im Allgemeinen nicht darauf verlassen, dass eine Hash-Code-Implementierung gleich bleibt, aber das Verhalten ist jetzt dokumentiert. Eine
java.lang.String
Änderung würde daher als Bruch bestehender Verträge gelten.Wo immer möglich, sollten Sie nicht auf Hash - Codes angewiesen , um das gleiche über Versionen bleiben usw. - aber in meinem Kopf
java.lang.String
ist ein Sonderfall , weil der Algorithmus hat angegeben ... solange Sie bereit bist , die Kompatibilität verlassen mit Releases vor dem Natürlich wurde ein Algorithmus angegeben.quelle
Ich habe etwas über JDK 1.0 und 1.1 gefunden und> = 1.2:
Etwas anderes, weil Sie anscheinend eine Nummer benötigen: Wie wäre es mit CRC32 oder MD5 anstelle von Hashcode und Sie können loslegen - keine Diskussionen und überhaupt keine Sorgen ...
quelle
Sie sollten sich nicht darauf verlassen, dass ein Hash-Code einem bestimmten Wert entspricht. Nur dass es konsistente Ergebnisse innerhalb derselben Ausführung zurückgibt. In den API-Dokumenten heißt es:
BEARBEITEN Da das Javadoc für String.hashCode () angibt, wie der Hash-Code eines Strings berechnet wird, würde ein Verstoß gegen diese die öffentliche API-Spezifikation verletzen.
quelle
Wie oben erwähnt, sollten Sie sich im Allgemeinen nicht darauf verlassen, dass der Hash-Code einer Klasse gleich bleibt. Beachten Sie, dass auch nachfolgende Ausführungen derselben Anwendung auf derselben VM ausgeführt werden möglicherweise unterschiedliche Hashwerte erzeugen. Die Hash-Funktion von AFAIK the Sun JVM berechnet bei jedem Lauf den gleichen Hash, dies ist jedoch nicht garantiert.
Beachten Sie, dass dies nicht theoretisch ist. Die Hash-Funktion für java.lang.String wurde in JDK1.2 geändert (der alte Hash hatte Probleme mit hierarchischen Zeichenfolgen wie URLs oder Dateinamen, da er tendenziell denselben Hash für Zeichenfolgen erzeugte, die sich nur am Ende unterschieden).
java.lang.String ist ein Sonderfall, da der Algorithmus von hashCode () (jetzt) dokumentiert ist, sodass Sie sich wahrscheinlich darauf verlassen können. Ich würde es immer noch als schlechte Praxis betrachten. Wenn Sie einen Hash-Algorithmus mit speziellen, dokumentierten Eigenschaften benötigen, schreiben Sie einfach einen :-).
quelle
Ein weiteres (!) Problem, über das Sie sich Sorgen machen müssen, ist die mögliche Änderung der Implementierung zwischen frühen / späten Java-Versionen. Ich glaube nicht, dass die Implementierungsdetails in Stein gemeißelt sind, und daher könnte ein Upgrade auf eine zukünftige Java-Version möglicherweise Probleme verursachen.
Fazit ist, ich würde mich nicht auf die Implementierung von verlassen
hashCode()
.Vielleicht können Sie mit diesem Mechanismus hervorheben, welches Problem Sie tatsächlich lösen möchten, und dies wird einen geeigneteren Ansatz hervorheben.
quelle
switch
Anweisungen über Zeichenfolgen zu Code kompiliert werden, der auf einem bestimmten festen Hash-Code basiert , würden Änderungen amString
Hash-Code-Algorithmus definitiv vorhandenen CodeNur um Ihre Frage zu beantworten und keine Diskussionen fortzusetzen. Die Apache Harmony JDK-Implementierung scheint einen anderen Algorithmus zu verwenden, zumindest sieht sie völlig anders aus:
Sun JDK
Apache Harmony
Fühlen Sie sich frei, es selbst zu überprüfen ...
quelle
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
Wenn ich mich nicht irre, liegt dies daran, dass Android die Implementierung des String-Objekts durch Sun ohne Änderungen verwendet.Wenn Sie sich Sorgen über Änderungen und möglicherweise inkompatible VMs machen, kopieren Sie einfach die vorhandene Hashcode-Implementierung in Ihre eigene Dienstprogrammklasse und generieren Sie damit Ihre Hashcodes.
quelle
Der Hashcode wird basierend auf den ASCII-Werten der Zeichen in der Zeichenfolge berechnet.
Dies ist die Implementierung in der String-Klasse wie folgt
Kollisionen im Hashcode sind unvermeidlich. Beispielsweise geben die Zeichenfolgen "Ea" und "FB" den gleichen Hashcode wie 2236 an
quelle