Ich habe zwei ArrayLists.
ArrayList A enthält:
['2009-05-18','2009-05-19','2009-05-21']
ArrayList B enthält:
['2009-05-18','2009-05-18','2009-05-19','2009-05-19','2009-05-20','2009-05-21','2009-05-21','2009-05-22']
Ich muss ArrayList A und ArrayList B vergleichen. Das Ergebnis ArrayList sollte die Liste enthalten, die in ArrayList A nicht vorhanden ist.
Das ArrayList-Ergebnis sollte sein:
['2009-05-20','2009-05-22']
wie zu vergleichen?
equals
, mit der Ihre Objekte verglichen werden können. Lesen Sie auch über die ImplementierunghashCode
. Beachten Sie beispielsweise , wieString::equals
ist case-sensitive , so „Apfel“ und „Apple“ wird nicht die gleiche betrachtet werden.removeAll
ruftfirstList.contains
jedes Element von aufsecondList
. Die Verwendung von aHashSet
würde dies verhindern und es gibt ein paar gute Antworten niedriger.Sie haben bereits die richtige Antwort. Und wenn Sie kompliziertere und interessantere Operationen zwischen Listen (Sammlungen) durchführen möchten, verwenden Sie Apache Commons-Sammlungen ( CollectionUtils ). Sie können Konjunktion / Disjunktion vornehmen, Schnittpunkte finden und prüfen, ob eine Sammlung eine Teilmenge einer anderen ist, und andere nette Dinge.
quelle
In Java 8 mit Streams ist das eigentlich ziemlich einfach. BEARBEITEN: Kann ohne Streams effizient sein, siehe unten.
Beachten Sie, dass der Hash-Satz nur einmal erstellt wird: Die Methodenreferenz ist an die enthaltene Methode gebunden. Um dasselbe mit Lambda zu tun, müsste die Menge in einer Variablen enthalten sein. Das Erstellen einer Variablen ist keine schlechte Idee, insbesondere wenn Sie sie unansehnlich oder schwerer zu verstehen finden.
Sie können das Prädikat ohne diese Dienstprogrammmethode (oder explizite Umwandlung) nicht einfach negieren , da Sie die Negativmethodenreferenz nicht direkt aufrufen können (Typinferenz ist zuerst erforderlich).
Wenn Streams eine
filterOut
Methode oder etwas anderes hätten, würde es besser aussehen.Auch @Holger gab mir eine Idee.
ArrayList
hat seineremoveAll
Methode für mehrere Entfernungen optimiert, es ordnet seine Elemente nur einmal neu. Es wird jedoch diecontains
von der angegebenen Sammlung bereitgestellte Methode verwendet , sodass wir diesen Teil optimieren müssen, wenn erlistA
alles andere als winzig ist.Mit
listA
undlistB
zuvor deklariert benötigt diese Lösung kein Java 8 und ist sehr effizient.quelle
Predicates.in(new HashSet<>(listA)).negate()
.ArrayList.remove
hat eine lineare Komplexität, ist jedochArrayList.removeAll
nicht aufremove
eine lineare Array-Aktualisierungsoperation angewiesen, sondern führt diese durch, wobei jedes verbleibende Element an seinen endgültigen Platz kopiert wird. Im Gegensatz dazu wurde die Referenzimplementierung vonLinkedList
nicht optimiert,removeAll
sondern führtremove
für jedes betroffene Element eine Operation aus, bei der jedes Mal bis zu fünf Referenzen aktualisiert werden. Also, je nach dem Verhältnis zwischen entfernt und den verbleibenden Elementen,ArrayList
‚sremoveAll
durchführen kann immer noch deutlich besser alsLinkedList
‘ s, sogar für große Listen.BEARBEITEN: In der ursprünglichen Frage wurde keine Sprache angegeben. Meine Antwort ist in C #.
Sie sollten stattdessen HashSet für diesen Zweck verwenden. Wenn Sie ArrayList verwenden müssen, können Sie die folgenden Erweiterungsmethoden verwenden:
mit HashSet ...
quelle
Ich habe Guava Sets.difference verwendet .
Die Parameter sind Mengen und keine allgemeinen Sammlungen, aber eine praktische Möglichkeit, Sätze aus jeder Sammlung (mit eindeutigen Elementen) zu erstellen, ist Guava ImmutableSet.copyOf (Iterable).
(Ich habe dies zuerst auf einer verwandten / betrogenen Frage gepostet , aber ich kopiere es auch hier, da ich denke , dass es eine gute Option ist, die bisher fehlt.)
quelle
Obwohl dies eine sehr alte Frage in Java 8 ist, könnten Sie so etwas tun
quelle
Collection
Methode habencontains
, ist sie sehr ineffizient. Es muss die gesamte Liste durchlaufen, wenn es nicht gefunden wird. Esa2
kann auf größeren Listen schmerzhaft langsam sein, es für jedes Element von zu tun , weshalb icha1
in meiner Antwort einen Satz daraus mache .Ich denke du redest über C #. Wenn ja, können Sie dies versuchen
quelle
b
Listea.Count
mal. Sie könnenHashSet
stattdessen eine erstellen , die für die verwendet werden soll,Contains
oder dieRemoveAll
Methode am Set verwenden, um genau die gewünschten Ergebnisse zu erzielen.Sie vergleichen nur Zeichenfolgen.
Fügen Sie die Werte in ArrayList A als Schlüssel in HashTable A ein. Fügen
Sie die Werte in ArrayList B als Schlüssel in HashTable B ein.
Entfernen Sie dann für jeden Schlüssel in HashTable A ihn aus HashTable B, falls vorhanden.
Was Ihnen in HashTable B übrig bleibt, sind die Zeichenfolgen (Schlüssel), die in ArrayList A keine Werte waren.
Beispiel für C # (3.0) als Antwort auf die Anforderung eines Codes hinzugefügt:
quelle
hashA
Variable praktisch nutzlos. Sie könnenlistA
stattdessen einen foreach mit erstellen, da dieserhashA
nur durchlaufen wird undContains
niemals aufgerufen wird.Hallo, benutze diese Klasse, dies vergleicht beide Listen und zeigt genau die Nichtübereinstimmung zwischen beiden Listen.
quelle
DIESE ARBEIT AUCH MIT Arraylist
quelle
remove
undcontains
durchsuchen müssen. Wenn Sie in einem Zyklus wiederholt aufgerufen werden (was in passiertremoveAll
), erhalten Sie eine quadratische Komplexität. Sie können jedoch ein Hash-Set verwenden und es nur linear haben.