Ersetzt das Hinzufügen eines doppelten Werts zu einem HashSet / HashMap den vorherigen Wert?

137

Bitte beachten Sie den folgenden Code:

HashSet hs = new HashSet();
hs.add("hi"); -- (1)
hs.add("hi"); -- (2)

hs.size()gibt 1, da HashSetkeine Duplikate zulässig sind, sodass nur ein Element gespeichert wird.

Ich möchte wissen, ob wir das doppelte Element hinzufügen. Ersetzt es dann das vorherige Element oder fügt es es einfach nicht hinzu?

Was passiert mit HashMapdem gleichen Fall?

Anand
quelle

Antworten:

246

Im Fall von HashMapwird der alte Wert durch den neuen ersetzt.

Im Fall von HashSetwird das Element nicht eingefügt.

Keppil
quelle
1
Sie sind sich nicht sicher, was ich vermisse, aber der Quellcode scheint etwas anderes anzuzeigen? Ich sehe, dass sie den Hintergrund nicht überprüfen, um festzustellen HashMap, ob der keybereits vorhanden ist, bevor sie putden Hintergrund aufrufen map.
Mystarrocks
10
@mystarrocks: Der Schlüssel ist das Element von Set, und das wird nie durch die put()Operation ersetzt.
Keppil
1
Ah, ich verstehe es jetzt. Ich habe verstanden, dass der Schlüssel das Element von ist Set, habe aber gerade erkannt, dass dies put()nur den Wert überschreibt, nicht den Schlüssel. In diesem Fall ist es derselbe Wert, der erneut neben den Schlüssel gesetzt wird. Dies kann besser sein oder auch nicht, als zu überprüfen, ob der Schlüssel vorhanden ist, und ihn zu setzen. In jedem Fall verstehe ich, wie es funktioniert.
Mystarrocks
Nur neugierig, warum HashMap und HashSet sich dafür entscheiden?
Helin Wang
@HelinWang: Ich glaube nicht, dass es geplant war, ich denke, es ist nur ein Effekt der HashSetImplementierung in Form von a HashMap. Schwer zu wissen, es sei denn, Sie sind einer der Entwickler der Klassen.
Keppil
47

Das erste, was Sie wissen müssen, ist, dass es sich HashSetwie ein verhält Set, was bedeutet, dass Sie Ihr Objekt direkt zum hinzufügen HashSetund es keine Duplikate enthalten kann. Sie fügen einfach Ihren Wert direkt hinzuHashSet .

Ist HashMapjedoch einMap Typ. Das bedeutet, dass Sie jedes Mal, wenn Sie einen Eintrag hinzufügen, ein Schlüssel-Wert-Paar hinzufügen.

In können HashMapSie doppelte Werte haben, aber keine doppelten Schlüssel. Im HashMapneuen Eintrag wird der alte ersetzt. Der letzte Eintrag wird in der seinHashMap .

Grundlegendes zur Verbindung zwischen HashMap und HashSet:

Denken Sie daran, HashMapkann keine doppelten Schlüssel haben. Hinter den Kulissen HashSetverwendet ein HashMap.

Wenn Sie versuchen, ein Objekt zu einem hinzuzufügen HashSet, wird dieser Eintrag tatsächlich als Schlüssel im HashMap- gespeichert HashMap, der auch hinter den Kulissen von verwendet wird HashSet. Da dieser Basiswert HashMapein Schlüssel-Wert-Paar benötigt, wird für uns ein Dummy-Wert generiert.

Wenn Sie nun versuchen, ein anderes doppeltes Objekt in dasselbe einzufügen HashSet, wird erneut versucht, es als Schlüssel in das HashMapdarunter liegende Objekt einzufügen . Allerdings HashMapbietet keine Unterstützung für Duplikate. Daher,HashSet wird immer noch nur ein Wert dieses Typs angezeigt. Nebenbei bemerkt, für jeden doppelten Schlüssel wird der Schlüssel überhaupt nicht ersetzt, da der für unseren Eintrag in HashSet generierte Wert ein Zufalls- / Dummy-Wert ist. Es wird ignoriert, da das Entfernen des Schlüssels und das Zurücksetzen desselben Schlüssels (der Dummy-Wert ist der gleiche) überhaupt keinen Sinn ergeben würde.

Zusammenfassung:

HashMaperlaubt Duplikate values, aber nicht keys. HashSetdarf keine Duplikate enthalten.

Um zu spielen, ob das Hinzufügen eines Objekts erfolgreich abgeschlossen wurde oder nicht, können Sie den booleanbeim Aufruf zurückgegebenen Wert überprüfen .add() und feststellen, ob er zurückgegeben wird trueoder false. Wenn es zurückgegeben wurde true, wurde es eingefügt.

Jimmy
quelle
HashMap allows duplicate valuesHashMap ersetzt den alten Wert durch den neuen.
Alex78191
20

Die Dokumente sind diesbezüglich ziemlich klar: ersetzt HashSet.add nicht :

Fügt das angegebene Element zu dieser Gruppe hinzu, falls es noch nicht vorhanden ist. Fügt formeller das angegebene Element e zu dieser Menge hinzu, wenn diese Menge kein Element e2 enthält, so dass (e == null? E2 == null: e.equals (e2)). Wenn diese Menge das Element bereits enthält, lässt der Aufruf die Menge unverändert und gibt false zurück.

Aber wird ersetzen:HashMap.put

Wenn die Zuordnung zuvor eine Zuordnung für den Schlüssel enthielt, wird der alte Wert ersetzt.

pb2q
quelle
4

Wenn es sich um HashSet handelt, wird es NICHT ersetzt.

Aus den Dokumenten:

http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add(E )

"Fügt das angegebene Element zu dieser Menge hinzu, wenn es noch nicht vorhanden ist. Fügt formeller das angegebene Element e zu dieser Menge hinzu, wenn diese Menge kein Element e2 enthält, so dass (e == null? E2 == null: e.equals ( e2)). Wenn diese Menge das Element bereits enthält, lässt der Aufruf die Menge unverändert und gibt false zurück. "

Bob Provencher
quelle
1

Korrigieren Sie mich, wenn ich falsch liege, aber was Sie erreichen, ist, dass mit Strings "Hi" == "Hi" nicht immer wahr wird (weil sie nicht unbedingt dasselbe Objekt sind).

Der Grund, warum Sie eine Antwort von 1 erhalten, ist, dass die JVM Zeichenfolgenobjekte nach Möglichkeit wiederverwendet. In diesem Fall verwendet die JVM das Zeichenfolgenobjekt erneut und überschreibt somit das Element in der Hashmap / Hashset.

Dieses Verhalten kann jedoch nicht garantiert werden (da es sich möglicherweise um ein anderes Zeichenfolgenobjekt handelt, das denselben Wert "Hi" hat). Das angezeigte Verhalten ist nur auf die Optimierung der JVM zurückzuführen.

Nick Rippe
quelle
0

Sie müssen zuerst die put-Methode in der Hash-Map überprüfen, da HashSet von HashMap gesichert wird

  1. Wenn Sie einen doppelten Wert hinzufügen, sagen Sie einen String "Eins" in HashSet.
  2. Ein Eintrag ("eins", PRESENT) wird in Hashmap eingefügt (für alle in set hinzugefügten Werte lautet der Wert "PRESENT", was vom Typ Object ist).
  3. Hashmap fügt den Eintrag in Map hinzu und gibt den Wert zurück, der in diesem Fall "PRESENT" oder null ist, wenn der Eintrag nicht vorhanden ist.
  4. Die add-Methode von Hashset gibt dann true zurück, wenn der von Hashmap zurückgegebene Wert gleich null ist, andernfalls false, was bedeutet, dass bereits ein Eintrag vorhanden ist ...
shiv
quelle
0

Anders ausgedrückt: Wenn Sie ein Schlüssel-Wert-Paar in eine HashMap einfügen, in der der Schlüssel bereits vorhanden ist (in gewissem Sinne gibt hashvalue () den gleichen Wert an und gleich () ist wahr, aber die beiden Objekte können sich dennoch auf verschiedene Weise unterscheiden ) wird der Schlüssel nicht ersetzt, aber der Wert wird überschrieben. Der Schlüssel wird nur verwendet, um den Hashwert () abzurufen und den Wert in der Tabelle damit zu finden. Da HashSet die Schlüssel einer HashMap verwendet und beliebige Werte festlegt, die (für den Benutzer) nicht wirklich wichtig sind, werden auch die Elemente des Satzes nicht ersetzt.

Marco Rothley
quelle
0

HashMapenthält im Grunde genommen, Entrywas später enthält Key(Object)und Value(Object).Intern HashSetsind HashMapund HashMapersetzen Werte, wie einige von Ihnen bereits gezeigt haben .. aber ersetzt es wirklich die Schlüssel ??? Nein ..und das ist der Trick hier. HashMapbehält seinen Wert als Schlüssel im Basiswert bei HashMapund der Wert ist nur ein Dummy-Objekt. Wenn Sie also versuchen, denselben Wert erneut in HashMap einzufügen (Schlüssel in der zugrunde liegenden Map). Ersetzt nur den Dummy-Wert und nicht den Schlüssel (Wert für HashSet).

Sehen Sie sich den folgenden Code für die HashSet-Klasse an:

public boolean  [More ...] add(E e) {

   return map.put(e, PRESENT)==null;
}

Hier ist e der Wert für HashSet, aber der Schlüssel für die zugrunde liegende Karte. Der Schlüssel wird niemals ersetzt. Ich hoffe, ich kann die Verwirrung beseitigen.

Kunal Kumar
quelle