2009-11-03 14 views
13

Einfache Frage.Vergleichen Sie zwei Listen für Updates, Löschungen und Ergänzungen

Ich habe eine neue Liste und eine alte Liste. Gibt es in Java einen Standardweg/eine Bibliothek, die es mir erlaubt, diese beiden Listen zu vergleichen und zu bestimmen, welche Artikel aktualisiert/gelöscht oder komplett neu sind? Z.B. Ich sollte am Ende mit drei Listen enden - Gelöschte Objekte (Elemente in alt, aber nicht in neu), Aktualisierte Elemente (Elemente in beiden), Neue Elemente (Elemente in neuen und nicht in alten).

Ich könnte das selbst schreiben, aber ich frage mich, ob es einen Standard Weg gibt, es zu tun.

Die Objekte in der Liste implementieren entspricht gleich.

+0

Sind Sie besorgt über die Reihenfolge der Listen? Zum Beispiel werden die bisher vorgeschlagenen Lösungen, die retainAll/removeAll beinhalten, nicht mit der Situation umgehen, in der die neue Liste die gleichen Elemente enthält wie die alte Liste, wenn auch in einer anderen Reihenfolge; z.B. {"foo", "bar"} vs {"bar", "foo"}. – Adamski

+0

Solange die equals-Methode korrekt implementiert ist, sehe ich nicht, warum die Reihenfolge sich auf removeAll etc. auswirken sollte. Gewiss nicht im javadoc vorschlagen: Entfernt alle Elemente aus der Liste, die in der angegebenen Sammlung enthalten sind (optionale Operation). – Pablojim

Antwort

31

Kein Standard Es tut mir leid. Sie können dies relativ einfach mit dem Standard-JDK tun, ohne auf eine Abhängigkeit von Apache Commons (wie von anderen vorgeschlagen) zurückgreifen zu müssen. Angenommen, Ihre Listen werden List<T> Instanzen:

List<T> oldList = ... 
List<T> newList= ... 

List<T> removed = new ArrayList<T>(oldList); 
removed.removeAll(newList); 

List<T> same = new ArrayList<T>(oldList); 
same.retainAll(newList); 

List<T> added = new ArrayList<T>(newList); 
added.removeAll(oldList); 
+0

+1 - ja, viel besser als meins. –

+1

Leider ist das ein bisschen falsch ... removeAll und ähnlich operieren auf der übergebenen Liste und geben einen booleschen Wert zurück. Das wird also nicht kompiliert. Muss sein: Liste hinzugefügt = neue ArrayList (newList); added.removeAll (alteListe); etc ... So könnte es einen Fall für die Apache Commons Methoden nach allem ... – Pablojim

+0

@Pablojim: ganz richtig, danke. Fest. – cletus

3

Ich würde Apache CollectionUtils verwenden und die Vereinigung (Elemente in beiden) und disjunction Funktionen verwenden (ändern Sie die Reihenfolge, um das eine oder andere zu erhalten).

Idealerweise würden Sie alle Elemente statt 3 durchgehen, aber wenn dies nicht Ihr Engpass ist, würde ich mir im Moment keine Gedanken über Effizienz machen.

7

In den Standardbibliotheken ist nichts enthalten.

jedoch die Apache Commons CollectionUtils Klasse gibt Ihnen diese Funktionalität mit der Kreuzung und subtrahieren Methoden:

Collection<T> old = ...; 
Collection<T> neww = ...; 

Collection<T> deleted = (Collection<T>)CollectionUtils.subtract(old, new); 
Collection<T> updated = (Collection<T>)CollectionUtils.intersection(old, new); 
Collection<T> newResult = (Collection<T>)CollectionUtils.subtract(new, old); 

(Sie müssen die (nicht markiert) wirft, weil CollectionUtils nicht generified ist.)

1

Ich glaube, Sie dies auch mit der Standard-Java-Bibliothek erreichen können. Werfen Sie einen Blick auf die folgenden Methoden der java.util.Collection:

retainAll (Sammlung c)

Behält nur die Elemente in dieser Sammlung, die in der angegebenen Sammlung (optional Betrieb) enthalten sind, . Mit anderen Worten: Entfernt aus dieser Sammlung alle Elemente, die nicht in der angegebenen Sammlung enthalten sind.

removeAll (Sammlung c)

entfernt diese alle Elemente Sammlung die auch in der angegebenen Sammlung (optional Betrieb) enthalten sind. Nachdem dieser Aufruf zurückgegeben wurde, enthält diese Sammlung keine Elemente gemeinsam mit der angegebenen Sammlung.

0

Wenn es eine Standardmethode ist, ich weiß es nicht ...
ich Collections sah aber nur sah disjunkt() (das ist schon eine Information ...) und indexOfSubList() (nicht sicher, wenn es überhaupt nützlich ist).
Ich schaute auch auf Google Collections und wenn es, anscheinend, nicht solche Einrichtung gibt, gibt es einige nützliche Werkzeuge dort, wie Collections2 's filter() -Funktion, die helfen kann, wenn Sie ein richtiges Prädikat machen.

[EDIT] Ich vermisste die removeAll und retainAll Methoden der Sammlung ... Ich lösche diese Antwort nicht, auch wenn ein bisschen erbärmlich, wie es irgendwie die anderen Antworten ergänzt ... (Ich denke, Google Sammlungen ist zumindest erwähnenswert!)

2

Persönlich glaube ich, dass der einzige vernünftige Weg, um den Unterschied zwischen zwei Listen zu erklären, ist mit einem ausgewachsenen Diff-Algorithmus (wie der des Unix-Diff-Befehl).

Sets, obwohl, sind eine viel einfachere Geschichte. Google Collections bietet eine Sets.difference(Set, Set) Methode sowie Union und Kreuzung.

Verwandte Themen