Frage
Heutzutage ist die Internet -Technologie ausgereift und immer mehr dezentralisiert, verteilt und stream Computing, was viele Dinge auf der Datenbankseite auf der Java -Seite aufgenommen hat. Heute fragte jemand, ob das Datenbankfeld keinen Index hat, wie sollte es basierend auf dem Feld dedupliziert werden? Alle sind einverstanden, Java zu verwenden, um es zu tun, aber wie geht es das?
Antwort
Plötzlich erinnerte ich mich an den Artikel, den ich in der Liste geschrieben habe, um schwere schwere Gewichte zu entfernen, und fand ihn und las ihn. Die Methode besteht darin, den HashCode umzuschreiben und die Methoden des Objekts in der Liste zu gleichzusetzen, in den Hashset zu werfen und dann herauszunehmen. Dies ist die Antwort, die ich wie ein Wörterbuch aufgeschrieben habe, als ich Java zum ersten Mal gelernt habe. Zum Beispiel können sie beim Interview Menschen, die seit 3 Jahren in Java sind, den Unterschied zwischen Set und HashMap auswendig lernen, aber sie wissen nicht, wie sie es implementieren sollen. Mit anderen Worten, Anfänger merken nur die Eigenschaften. Wenn Sie es jedoch tatsächlich in einem Projekt verwenden, müssen Sie sicherstellen, dass es wahr ist. Da die Bestätigung nutzlos ist, kann ich nur an das Ergebnis glauben. Sie müssen wissen, wie Hashset mir hilft, das schwere Gewicht zu entfernen. Wenn Sie darüber nachdenken, können Sie die schwere Last ohne Hashset entfernen? Der einfachste und direkteste Weg ist es, es jedes Mal mit historischen Daten zu vergleichen und sie in den Schwanz der Warteschlange einzulegen, wenn es anders ist. Und Hashset beschleunigt diesen Prozess nur.
Geben Sie dem Objektbenutzer zunächst sortiert
@Data@builder@allargSconstructorPublic -Klasse Benutzer {private Integer id; privater String -Name;} List <Unter> users = lists.NewarrayList (neuer Benutzer (1, "A"), neuer Benutzer (1, "B"), neuer Benutzer (2, "B"), neuer Benutzer (1, "A");Ziel ist es, den Benutzer ohne doppelte ID herauszunehmen. Um Streit zu verhindern, gebe ich eine Regel. Nehmen Sie einfach Daten mit eindeutigen IDs nach Belieben aus und müssen nicht gewissenhaft sein, welche berechnet wird, wenn die ID gleich ist.
Verwenden Sie die intuitivste Methode
Diese Methode besteht darin, eine leere Liste zu verwenden, um die durchquerten Daten zu speichern.
@Testpublic void dis1 () {list <Benutzer> result = new LinkedList <> (); für (Benutzer Benutzer: Benutzer) {boolean b = result.stream (). Anymatch (u -> u.getId (). Equals (user.getId ()); if (! b) {result.add (Benutzer); }} System.out.println (Ergebnis);}Hashset verwenden
Jemand, der die Merkmale auswendig gelernt hat, weiß, dass Hashset schwere Gewichte entfernen kann. Wie entferne ich also schwere Gewichte? Merken Sie es ein wenig tiefer und entsprechen den Methoden von Hashcode und gleich. Wie basiert es also auf diesen beiden? Personen, die den Quellcode nicht gelesen haben, können nicht fortgesetzt werden, und das Interview endet hier.
Tatsächlich wird Hashset von HashMap implementiert (ich habe den Quellcode noch nie gesehen und habe immer intuitiv gedacht, dass der Schlüssel von HashMap durch Hashset implementiert wird, was genau das Gegenteil ist). Ich werde die Beschreibung hier nicht erweitern, nur die Konstruktionsmethode ansehen und die Methode von Hashset hinzufügen, um sie zu verstehen.
public hashset () {map = new HashMap <> ();}/*** Natürlich gibt es bei es falsch zurück, wenn es nicht existiert, es gibt wahre*/public boolean add (e) {return map.put (e, präsent) == null;}Daraus ist auch zu erkennen, dass die Wiederholung von Hashset basierend auf HashMap implementiert wird und die Implementierung von HashMap vollständig auf den HashCode- und Equals -Methoden beruht. Jetzt ist es vollständig geöffnet. Wenn Sie Hashset verwenden möchten, müssen Sie Ihre beiden Methoden optimistisch sein.
In dieser Frage müssen wir basierend auf der ID deduplizieren, daher ist unsere Vergleichsbasis ID. Modifikationen sind wie folgt:
@Overridepublic Boolean Equals (Objekt o) {if (this == o) {return true; } if (o == null || getClass ()! = o.getClass ()) {return false; } User user = (user) o; return object.equals (id, user.id);}@oversidepublic int HashCode () {return Objects.hash (id);} // HashCoderesult = 31 * result + (element == null? 0: element.hashcode ());Unter ihnen ruft Objekte Arrays 'HashCode auf, und der Inhalt ist wie oben gezeigt. Multiplizieren Sie mit 31 gleich x << 5-x.
Die endgültige Implementierung ist wie folgt:
@Testpublic void dis2 () {set <Bener> result = new Hashset <> (Benutzer); System.out.println (Ergebnis);}Verwenden Sie Java Stream, um zu deduplizieren
Wenn Sie auf die erste Frage zurückkehren, ist der Grund, diese Frage zu stellen, darin, dass die Datenmenge, wenn Sie die Datenbankseite auf die Java-Seite wieder aufnehmen möchten, relativ groß sein kann, z. B. 100.000 Stück. Für Big Data ist die Verwendung von Stream-bezogenen Funktionen am einfachsten. So wie Stream auch die eigene Funktion liefert. Wie sollte es verwendet werden?
user.ParallelStream (). DISTECTION (). foreach (System.out :: println);
Ich sah Lambda nicht als Parameter, dh wurden keine benutzerdefinierten Bedingungen erteilt. Glücklicherweise markierte Javadoc den Deduplizierungsstandard:
Gibt einen Stream zurück, der aus den unterschiedlichen Elementen (gemäß {@link Object#Equals (Object)}) dieses Streams besteht.Wir wissen, dass wir uns auch dieses Prinzip auswendig lernen müssen: Wenn Equals true zurückgibt, muss der Rückgabewert von HashCode gleich sein. Dies ist ein wenig logisch verwirrend beim Auswendiglernen, aber solange wir die Implementierungsmethode von HashMap verstehen, werden wir uns nicht schwer zu sprechen fühlen. HashMap findet zunächst nach der HashCode -Methode und vergleicht dann die Equals -Methode.
Um die Verwendung von Deduplizierung eindeutig zu verwenden, müssen Sie den HashCode und gleiche Methoden überschreiben, es sei denn, Sie verwenden die Standardeinstellung.
Also, warum machst du das? Klicken Sie in die Implementierung.
<p_in> Knoten <T> record (pipelineHelper <t> Helfer, Splitter <P_in> Splitter) {// Wenn der Stream sortiert ist, sollte er auch bestellt werden, sodass das Folgende auch den Sortier -Ordinalop <T, LinkedHashset <T >> reciopt = recised. LinkedHashset :: add, linkedHashset :: addall); Return Knode.Node (recordOP.ValuateParallel (Helfer, Splitterer));}Die interne Implementierung wird durch Reduzierung erreicht. Wenn Sie an eine Reduzierung denken, denken Sie sofort an eine Methode zur Implementierung von DifferentByKey. Ich muss nur Reduzierung verwenden, und der Berechnungsteil besteht darin, die Stream-Elemente mit einem eingebauten HashMap zu vergleichen, sie zu überspringen, wenn es vorhanden ist, und sie einsetzen, wenn es keine gibt. Tatsächlich ist die Idee am Anfang die einfachste Methode.
@TestPublic void dis3 () {user.ParallelStream (). Filter (differenzByKey (user :: getId)) .foreach (System.out :: println);} public static <t> predicate <T> charakteristisch (function <? Super t,?> KeyExtractor) {set <Toject <t> differenz = condenthykey (function <? Super t,?> KeyExtractor) {set <-Objection> -Spinne = concor = concurentHashKey.) return t -> siehe.add (keyextractor.apply (t));}Wenn es sich um einen parallelen Strom handelt, ist derjenige, der genommen wird, nicht unbedingt der erste, sondern zufällig.
Die obige Methode ist die beste gefunden und nicht invasiv. Aber wenn Sie eindeutig verwenden müssen. Sie können Hashcode nur umschreiben und gleich wie die Hashset -Methode.
Zusammenfassung
Sie können nur üben, ob Sie diese Dinge selbst verwenden können. Andernfalls ist es schwierig, sie sofort herauszunehmen, wenn Sie sie wirklich verwenden möchten, oder Sie werden das Risiko eingehen. Und wenn Sie es wirklich mutig verwenden möchten, ist es auch notwendig, die Regeln und Implementierungsprinzipien zu verstehen. Wie unterscheiden sich die Implementierungen von LinkedHashset und Hashset beispielsweise?
Mit dem einfachen LinkedHashset -Quellcode angehängt:
öffentliche Klasse LinkedHashset <E> erweitert Hashset <e> implementiert set <e>, klonbar, java.io.serializable {private statische endgültige lange Serialversionuid = -2851667679971038690L; public linkedHashset (int initialCapacity, float loadFactor) {super (initialCapacity, loadFactor, true); } public linkedHashset (init initialCapacity) {super (initialCapacity, .75f, true); } public linkedHashset () {super (16, .75f, true); } public linkedHashset (Sammlung <? Erweitert E> c) {Super (math.max (2*c.Size (), 11), .75f, true); Addall (c); } @Override public Splitters <E> Sprecher () {return Splitterators.Spliterator (this, Splatter. }}Wieder auffüllen:
Methode zum Entfernen von doppelten Daten aus der Listensammlung in Java
1. Schleifen Sie alle Elemente in der Liste und löschen Sie dann Duplikate
public static list REMODEDUPLICE (Listliste) {für (int i = 0; i <list.size () - 1; i ++) {for (int j = list.size () - 1; j> i; j -) {if (list.get (j) .Equals (list.get (i)) {list.remove (j); }}} Rückgabeliste; } 2. Starten Sie doppelte Elemente durch Hashset
public static list remedUplicate (Listliste) {Hashset H = new Hashset (Liste); list.clear (); list.addall (h); Rückgabeliste; }3.. Löschen Sie doppelte Elemente in ArrayList, um die Reihenfolge aufrechtzuerhalten
// doppelte Elemente in ArrayList löschen, bestellen Sie öffentliche statische void RemedupliceWithorder (Listliste) {set set = new Hashset (); Liste newList = new ArrayList (); für (iterator iter = list.iterator (); iter.hasnext ();) {Object element = iter.Next (); if (set.add (element)) newList.add (Element); } list.clear (); list.addall (NewList); System.out.println ("Duplicate entfernen" + Liste); }V.
public static list removedUplicate (Listliste) {listTTemp = new ArrayList (); für (int i = 0; i <list.size (); i ++) {if (! listTemp.contains (list.get (i))) {listTemp.add (list.get (i)); }} return listTemp; }