Verwendung von String.hashCode zum Generieren von Primärschlüsseln

7

Ich verstehe, dass dies bereits diskutiert zu sein scheint und die Antwort ist ja, String.hashCode kann gleiche Werte für verschiedene Strings erzeugen, aber ziemlich unwahrscheinlich ( Kann der hashCode von Java denselben Wert für verschiedene Strings erzeugen? ). Allerdings passiert es in meiner Anwendung.

Der folgende Code erzeugt den gleichen Hashcode: -347019262 (jave 1.7.25)

%Vor%

Ich brauche in diesem Fall Hashcode, und ich möchte damit einen eindeutigen Primärschlüssel für eine Zeichenkette erzeugen. es scheint, dass ich es nicht richtig mache. Irgendwelche Vorschläge bitte?

Vielen Dank!

    
Ziqi 11.03.2014, 10:47
quelle

5 Antworten

13

Sie missverstehen .hashCode() .

Ein Teil des Vertrags ist, dass Objekte, die equals() sind, dieselbe hashCode() haben müssen. Das Gegenteil ist jedoch nicht der Fall: Zwei Objekte, die dieselbe hashCode() do nicht haben, müssen equals() sein.

Dies ist eine gültige, wenn auch völlig nutzlose hashCode() Implementierung:

%Vor%

Sie sollten die Zeichenfolge selbst als "Primärschlüssel" verwenden. Wenn Sie einen "effizienteren" Schlüssel wünschen, sollten Sie überlegen, welches Format die Eingabezeichenfolge hat und, wenn möglich, einen wesentlichen Teil dieser Eingabe extrahieren.

    
fge 11.03.2014 10:50
quelle
4

Die sinnvollste Option ist die Verwendung der Zeichenfolge als Primärschlüssel. (Eine andere Möglichkeit wäre, Ihrem Datensatz eine GUID zuzuordnen und diese als Primärschlüssel zu verwenden.)

Das Hashing ist (1) schnell und (2) so, dass zwei gleiche Strings denselben Hash-Code haben.

Ich würde vorschlagen, dass wahrscheinlich ist, dass Sie Hashing-Konflikte bekommen ; immerhin hat ein int (der Hash-Rückgabetyp) nur etwa 4 Milliarden verschiedene Werte.

    
Bathsheba 11.03.2014 10:50
quelle
2

Sie können den SHA1-Hash-Algorithmus verwenden, um die Kollisionswahrscheinlichkeit zu reduzieren. Werfen Sie einen Blick auf diese Schnipsel, um zu sehen, wie SHA1-Hash in Java berechnet wird: Ссылка

    
Boris Brodski 11.03.2014 10:51
quelle
2

Sie könnten

verwenden %Vor%

um die einzigartigen Ergebnisse zu erhalten.

BEARBEITEN

Ich dachte, das könnte die murmur hash sein. Die Guava-Implementierung könnte auch hier helfen:

%Vor%

Generell soll murmur hash schnell und zuverlässig sein.

    
Eugene 11.03.2014 10:53
quelle
2
  

Ich brauche in diesem Fall Hashcode, und ich möchte damit einen eindeutigen Primärschlüssel für eine Zeichenkette erzeugen. es scheint, dass ich es nicht richtig mache. Irgendwelche Vorschläge bitte?

Sie sollten bei der Verwendung von Primärschlüsseln für Hashwerte immer vorsichtig sein. Sie sind nicht einzigartig. Je kleiner der Bereich der Hash-Funktion ist, desto schlechter ist das Problem.

In Ihrem Fall generiert hashcode (und die in einem Kommentar vorgeschlagene Methode identityHashcode() ) einen 32-Bit-Wert. Für jedes Paar von zwei zufällig generierten Strings besteht eine Chance von 1 in 2 ^ 32, dass die Hashcodes gleich sind. Dies gilt für die Methode any zum Erzeugen von Hash-Codes (32 Bit).

Nun scheint eine Chance von (ungefähr) 1 zu 2 Milliarden nicht viel zu sein. Aber du brauchst nicht nur paarweise Einzigartigkeit. Sie müssen alle der Hashcodes Ihrer Zeichenfolgen eindeutig sein ..., weil Sie versuchen, die Hashcodes als Primärschlüssel zu verwenden, und Primärschlüssel müssen eindeutig sein. Und die Tabelle auf der Wikipedia-Seite " Geburtstagsproblem " sagt, dass man nur etwa 50.000 Schlüssel benötigt, bevor die Wahrscheinlichkeit einer Kollision steigt zu 1 in 4. (Ja ... EINS in VIER!)

Kurz gesagt, verwenden Sie nicht hashcode() -Werte als Primärschlüssel.

Die gleiche Tabelle zeigt eine gute Hash-Funktion an, die 128 Bit Hash-Werte erzeugt, die wahrscheinlich gut genug sind, um Kollisionen zu vermeiden. Aber prüfe die Wahrscheinlichkeiten für dich selbst und entscheide selbst.

    
Stephen C 11.03.2014 11:44
quelle

Tags und Links