In Java befindet sich ein Satz, der keine doppelten Elemente enthält, oder um genau ein Elementpaar zu sein, das nicht E1.Equals (E2) enthält. Null ist im Set erlaubt. SET kann die Reihenfolge der Elemente im Set nicht garantieren.
Wenn das festgelegte Element hinzugefügt wird und das angegebene Element nicht vorhanden ist, ist die Zugabe erfolgreich. Das heißt, wenn das Element E1 im Satz nicht existiert (e == null? E1 == null: e.queals (e1)), kann E1 zum Satz hinzugefügt werden.
Hier ist ein festgelegter Implementierungsklassen -Hashset als Beispiel und führt kurz das Prinzip der Set ein, um die Implementierung nicht zu wiederholen:
Paket com.darren.test.overide; öffentliche Klasse CustomString {private String -Wert; public CustomString () {this ("");} public CustomString (String -Wert) {this.Value = value;}} Paket com.darren.test.overide; import Java.util.hashset; import Java.util.set; public class hashsettest {public static void main (String [] args) {String a = new String ("a"); String b = New String ("a"); CustomString ("B"); System.out.println ("A.equals (b) ==" + A.equals (b)); System.out.println ("C.Equals (d) ==" + C.Equals (d)); set <elements set = new = new Hashset <Object> (); set.add (a); set.add (b); set.add (c); set.add (d);Die Betriebsergebnisse sind wie folgt:
A.equals (b) == true c.equals (d) == false set.size () == 3 com.darren.test.overide.customstring@2c39d2 a com.darren.test.overide.customstring@5795ce
Vielleicht haben Sie den Schlüssel gesehen, das stimmt, es ist die Equals -Methode. Es ist immer noch unangemessen, dies zu sagen, aber um genau zu sein, sollte es die gleichen und Hashcode -Methoden sein. Warum sagst du das? Ändern wir die CustomString -Klasse und testen wir sie:
package com.darren.test.overide;public class CustomString {private String value;public CustomString() {this("");}public CustomString(String value) {this.value = value;}@Override public Boolean equals(Object obj) {if (this == obj) {return true;} else if (obj instanceof CustomString) {CustomString customString = (CustomString) obj; customString.Value.equals (value);} else {return false;}}}Testergebnisse:
A.equals (b) == true c.equals (d) == true set.size () == 3 com.darren.test.overide.customstring@12504e0 a com.darren.test.overide.customstring@1630eb6
Der Rückgabewert von Equals ist diesmal wahr, aber die Größe des Satzes beträgt immer noch 3.
Lassen Sie uns weiter verändern
Paket com.darren.test.overide; öffentliche Klasse CustomString {private String -Wert; public CustomString () {this ("");} public CustomString (String -Wert) {this.value = value;}@überschreiben öffentliche int HashCode () {// return Super.hashCode (); Rückgabe 1;}}Schauen Sie sich die Ergebnisse noch einmal an:
A.equals (b) == true c.equals (d) == false set.size () == 3 com.darren.test.overide.customstring@1 com.darren.test.overide.customstring@1 a
Schreiben Sie nur die HashCode
Schließlich ändern Sie es
package com.darren.test.overide;public class CustomString {private String value;public CustomString() {this("");}public CustomString(String value) {this.value = value;}@Override public Boolean equals(Object obj) {if (this == obj) {return true;} else if (obj instanceof CustomString) {CustomString customString = (CustomString) obj; return CustomString.Value.equals (value);} else {return false;}}@override public int HashCode () {// return Super.hashCode (); Rückgabe 1;}}Endergebnisse:
A.equals (b) == true c.equals (d) == true set.size () == 2 com.darren.test.overide.customstring@1 a
OK, es wird bewiesen, dass Sie die Equals -Methode und die Hashcode -Methode neu schreiben und das Prinzip sehen müssen:
Konvention für Hashcode in java.lnag.Object:
1. Während einer Anwendungsausführung wird die HashCode -Methode, wenn die zum Vergleich der Equals -Methode eines Objekts verwendeten Informationen verwendet werden, die HashCode -Methode mehrmals auf dem Objekt aufgerufen und muss konsequent dieselbe Ganzzahl zurückgeben.
2. Wenn die beiden Objekte gemäß der Equals -Methode (Objecto) gleich sind, muss das Aufrufen der HashCode -Methode eines der beiden Objekte das gleiche ganzzahlige Ergebnis erzielen.
3. Wenn die beiden Objekte gemäß der Equals -Methode (Objekto) nicht gleich sind, wird die HashCode -Methode eines der beiden Objekte aufgerufen, und es sind keine unterschiedlichen Ganzzahlergebnisse erforderlich. Wenn es jedoch anders sein kann, kann es die Leistung der Hash -Tabelle verbessern.
In Hashset werden die grundlegenden Vorgänge von der HashMap -Schicht implementiert, da die Hashset -Schicht HashMap zum Speichern von Daten verwendet. Berechnen Sie beim Hinzufügen eines Elements zu einem Hashset zuerst den HashCode -Wert des Elements und verwenden Sie dann diesen (HashCode des Elements)% (die Größe der HashMap -Sammlung) + 1, um den Speicherort dieses Elements zu berechnen. Wenn diese Position leer ist, fügen Sie das Element hinzu. Wenn es nicht leer ist, verwenden Sie die Equals -Methode, um zu vergleichen, ob die Elemente gleich sind, und fügen Sie es nicht hinzu, fügen Sie sie nicht hinzu, suchen Sie einen leeren Speicherplatz, um ihn hinzuzufügen.
Das Folgende ist Teil des Quellcode von Hashset:
Package Java.util; öffentliche Klasse Hashset <e> erweitert AbstractSet <e> implements set <e> klonbar, java.io.serializierbar {statische endgültige long serialversionuid = -5024744406713321676L; // Die zugrunde liegende Schicht verwendet Hastehmap, um alle Elemente zu sparen. Private Transient Hashmap <e, Object> MAP; // Definieren Sie ein virtuelles Objekt Objekt als Wert von HashMap und definieren Sie dieses Objekt als statisches Finale. private statisches endgültiges Objekt präsent = new Object ();/*** Der parameterlose Standardkonstruktor konstruiert einen leeren Hashset. * * Tatsächlich initialisiert die zugrunde liegende Schicht eine leere Hashmap und verwendet die Standard -Anfangskapazität von 16 und den Ladefaktor von 0,75. */public hashset () {map = new HashMap <e, Object> ();}/*** Konstruieren Sie einen neuen Satz, der die Elemente in der angegebenen Sammlung enthält. * * Die tatsächliche zugrunde liegende Ebene verwendet den Standardlastfaktor 0,75 und reicht aus, um die anfängliche Kapazität aller Elemente in der angegebenen * Sammlung zu enthalten, um eine HashMap zu erstellen. * @param c Die darin enthaltenen Elemente werden in der Sammlung in diesem Satz gespeichert. */public Hashset (Sammlung <erweitert e> c) {map = new HashMap <e, Object> (math.max ((int) (C.Size ()/. 75f) + 1, 16)); AddAll (c);}/*** Konstruieren Sie ein leeres Hashset mit der angegebenen Initialkapazität und Lastfaktor. * * Die tatsächliche zugrunde liegende Schicht konstruiert einen leeren HashMap mit entsprechenden Parametern. * @param initialCapacity Anfangskapazität. * @Param LoadFactor Lastfaktor. */public hashset (intit initialCapacity, float loadFactor) {map = new HashMap <e, Objekt> (InitialCapacity, LoadFactor);}/*** Konstruieren Sie ein leeres Hashset mit der angegebenen InitialCapacity. * * Tatsächlich konstruiert die zugrunde liegende Schicht einen leeren Hashmap mit den entsprechenden Parametern und dem Lastfaktor -Lastfaktor von 0,75. * @param initialCapacity Anfangskapazität. */public Hashset (intit initialCapacity) {map = new HashMap <e, Object> (InitialCapacity);}/*** Konstruieren Sie eine neue leere Link -Hash -Sammlung mit der angegebenen InitialCapacity und LoadFactor. * Dieser Konstruktor ist die Erlaubnis zur Verpackung des Zugriffs und ist der Öffentlichkeit nicht ausgesetzt. Es ist eigentlich nur Unterstützung für LinkedHashset. * * Tatsächlich erstellt die zugrunde liegende Ebene eine leere LinkedHasMap -Instanz mit den angegebenen Parametern, um sie zu implementieren. * @param initialCapacity Anfangskapazität. * @Param LoadFactor Lastfaktor. * @param Dummy -Tag. */Hashset (intit initialCapacity, float loadfactor, boolean dummy) {map = new LinkedHasMap <e, Objekt> (InitialCapacity, LoadFactor);}/*** Gibt den Iterator zurück, der die Elemente in diesem Satz iteratiert. Die Reihenfolge der Rückgabeelemente ist nicht spezifisch. * * Die zugrunde liegende Ebene ruft tatsächlich den Schlüsselset des zugrunde liegenden Hashmap auf, um alle Schlüssel zurückzugeben. * Die Elemente im Hashset sind zu sehen, werden jedoch auf dem Schlüssel des zugrunde liegenden Hashmap gespeichert, und der Wert wird durch ein statisches endgültiges Objektobjekt identifiziert. * @return Iterator, die in diesem Satz Elemente über Elemente iteriert. */@Override public iterator <e> iterator () {return map.keyset (). Iterator ();}/*** Gibt die Anzahl der Elemente in diesem Satz zurück (die Kapazität des Satzes). * * Die zugrunde liegende Ebene ruft tatsächlich die Methode der size () von HashMap auf, um die Anzahl der Eingaben zurückzugeben, und erhält die Anzahl der Elemente im Satz. * @return die Anzahl der Elemente in diesem Satz (Kapazität des Satzes). */@Override public int size () {return map.size ();}/*** return true, wenn dieser Satz keine Elemente enthält. * * Die zugrunde liegende Schicht ruft tatsächlich Isempty () von HashMap auf, um festzustellen, ob das Hashset leer ist. * @return return true, wenn dieses Satz keine Elemente enthält. */@Override public boolean isEmpty () {return map.isempty ();}/*** return true, wenn dieses Satz das angegebene Element enthält. * Insbesondere wird True zurückgegeben, wenn und nur dann ein E -Element enthält, das erfüllt (o == null? E == null: o.equals (e)) *. * * Der enthält den zugrunde liegenden tatsächlichen Aufruf an HashMap bestimmt, ob er den angegebenen Schlüssel enthält. * @param o Die Existenz des Elements in diesem Satz wurde getestet. * @return return true, wenn dieses Satz das angegebene Element enthält. */@Override public boolean enthält (Objekt o) {return map.containsKey (o);}/*** Wenn das angegebene Element in diesem Satz nicht enthalten ist, fügen Sie das angegebene Element hinzu. * Insbesondere, wenn dieser Satz kein Element E2 enthält, das erfüllt (e == null? E2 == null: eequals (e2)) * wird das angegebene Element E diesem Satz hinzugefügt. * Wenn dieser Satz bereits das Element enthält, ändert der Anruf nicht den Satz und gibt false zurück. * * Die zugrunde liegende Ebene wird das Element tatsächlich als Schlüssel in die Hashmap einfügen. * Da die Put () -Methode von Hashmap ein Schlüsselwertpaar hinzufügt, ist der Schlüssel des HashMap-neuen Eintrags * der Schlüssel des ursprünglichen Eintrags in der Sammlung (HashCode () gilt gleich, und es gibt auch über den Equals-Vergleich das Richtige zurück. * Wenn dem Hashset ein vorhandenes Element hinzugefügt wird, wird das neu hinzugefügte Sammelelement nicht in den HashMap eingebracht, und * ändert sich das ursprüngliche Element nicht, was das Merkmal der Nicht-Repetition von Elementen im Set erfüllt. * @param e Elemente, die zu diesem Satz hinzugefügt werden. * @return return true, wenn dieser Satz das angegebene Element nicht enthält. */@Override public boolean add (e e) {return map.put (e, präsent) == null;}/*** Wenn das angegebene Element in diesem Satz vorhanden ist, wird es entfernt. * Insbesondere, wenn dieses Satz ein Element E enthält, das erfüllt (o == null? E == null: o.equals (e)), wird es entfernen. Rückgabe true, wenn dieser Satz bereits das Element enthält (OR: TRUE, wenn sich dieser Satz aufgrund des Anrufs ändert). (Sobald der Anruf zurückgegeben wird, enthält dieser Satz das Element nicht mehr). * * Die zugrunde liegende Ebene ruft tatsächlich die Methode von HashMap auf, um den angegebenen Eintrag zu löschen. * @Param O -Objekt, das entfernt werden muss, wenn es in diesem Satz vorliegt. * @return return true, wenn eingestellt das angegebene Element enthält. */@Override public boolean remove (Objekt o) {return map.remove (o) == präsent;}/*** Entfernen Sie alle Elemente aus diesem Satz. Nachdem dieser Anruf zurückgegeben wird, ist das Set leer. * * Die zugrunde liegende Ebene ruft tatsächlich die klare Methode von HashMap auf, um alle Elemente im Eintrag zu löschen. */@Override public void clear () {map.clear ();}}Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels über die Analyse des Prinzips der Hashset -Entfernung doppelter Werte. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!