Finden der Unterschiede zwischen zwei Listen in Java

1. Übersicht

Das Auffinden von Unterschieden zwischen Sammlungen von Objekten desselben Datentyps ist eine häufige Programmieraufgabe. Stellen Sie sich als Beispiel vor, wir haben eine Liste von Studenten, die sich für eine Prüfung beworben haben, und eine andere Liste von Studenten, die sie bestanden haben. Der Unterschied zwischen diesen beiden Listen würde uns die Studenten geben, die die Prüfung nicht bestanden haben.

In Java gibt es keine explizite Möglichkeit, Unterschiede zwischen zwei Listen in der Listen- API zu finden, obwohl es einige Hilfsmethoden gibt, die nahe kommen.

In diesem kurzen Tutorial sehen wir uns an, wie Sie die Unterschiede zwischen den beiden Listen finden . Wir werden einige verschiedene Ansätze ausprobieren, einschließlich Java (mit und ohne Streams ) und die Verwendung von Bibliotheken von Drittanbietern wie Guava und den Apache Commons-Sammlungen .

2. Setup testen

Beginnen wir mit der Definition von zwei Listen, anhand derer wir unsere Beispiele testen:

public class FindDifferencesBetweenListsUnitTest { private static final List listOne = Arrays.asList("Jack", "Tom", "Sam", "John", "James", "Jack"); private static final List listTwo = Arrays.asList("Jack", "Daniel", "Sam", "Alan", "James", "George"); }

3. Verwenden der Java List API

Mit der List- Methode removeAll () können wir eine Kopie einer Liste erstellen und dann alle mit der anderen Liste gemeinsamen Elemente entfernen :

List differences = new ArrayList(listOne); differences.removeAll(listTwo); assertEquals(2, differences.size()); assertThat(differences).containsExactly("Tom", "John");

Lassen Sie uns dies umkehren, um die Unterschiede umgekehrt zu finden:

List differences = new ArrayList(listTwo); differences.removeAll(listOne); assertEquals(3, differences.size()); assertThat(differences).containsExactly("Daniel", "Alan", "George");

Wir sollten auch beachten, dass List auch eine RetainAll- Methode enthält , wenn wir die gemeinsamen Elemente zwischen den beiden Listen finden möchten .

4. Verwenden der Streams-API

Ein Java- Stream kann zum Ausführen sequentieller Operationen an Daten aus Sammlungen verwendet werden, einschließlich des Filterns von Unterschieden zwischen Listen :

List differences = listOne.stream() .filter(element -> !listTwo.contains(element)) .collect(Collectors.toList()); assertEquals(2, differences.size()); assertThat(differences).containsExactly("Tom", "John");

Wie in unserem ersten Beispiel können wir die Reihenfolge der Listen ändern, um die verschiedenen Elemente aus der zweiten Liste zu finden:

List differences = listTwo.stream() .filter(element -> !listOne.contains(element)) .collect(Collectors.toList()); assertEquals(3, differences.size()); assertThat(differences).containsExactly("Daniel", "Alan", "George");

Wir sollten beachten, dass der wiederholte Aufruf von List . enthält () kann für größere Listen eine kostspielige Operation sein.

5. Verwenden von Bibliotheken von Drittanbietern

5.1. Verwenden von Google Guava

Guave enthält ein handliches Set . Differenz - Methode , aber es zu benutzenmüssen wir zuerst unsere konvertieren Liste zu einem Set :

List differences = new ArrayList(Sets.difference(Sets.newHashSet(listOne), Sets.newHashSet(listTwo))); assertEquals(2, differences.size()); assertThat(differences).containsExactlyInAnyOrder("Tom", "John");

Wir sollten beachten, dass das Konvertieren der Liste in einen Satz den Effekt hat, dass sie dedupliziert und neu angeordnet wird.

5.2. Verwenden von Apache Commons-Sammlungen

Die CollectionUtils- Klasse aus Apache Commons Collections enthält eine removeAll- Methode.

Diese Methode funktioniert genauso wie List . removeAll und erstellt gleichzeitig eine neue Sammlung für das Ergebnis :

List differences = new ArrayList((CollectionUtils.removeAll(listOne, listTwo))); assertEquals(2, differences.size()); assertThat(differences).containsExactly("Tom", "John");

6. Umgang mit doppelten Werten

Schauen wir uns nun die Unterschiede an, wenn zwei Listen doppelte Werte enthalten.

Um dies zu erreichen, müssen wir die doppelten Elemente aus der ersten Liste entfernen, genau so oft, wie sie in der zweiten Liste enthalten sind.

In unserem Beispiel erscheint der Wert "Jack" zweimal in der ersten Liste und nur einmal in der zweiten Liste:

List differences = new ArrayList(listOne); listTwo.forEach(differences::remove); assertThat(differences).containsExactly("Tom", "John", "Jack");

Dies können wir auch mit der Subtraktionsmethode von Apache Commons Collections erreichen :

List differences = new ArrayList(CollectionUtils.subtract(listOne, listTwo)); assertEquals(3, differences.size()); assertThat(differences).containsExactly("Tom", "John", "Jack");

7. Fazit

In diesem Artikel haben wir einige Möglichkeiten untersucht, um Unterschiede zwischen Listen zu finden .

In den Beispielen haben wir eine grundlegende Java-Lösung behandelt , eine Lösung, die die Streams- API verwendet, sowie Bibliotheken von Drittanbietern wie Google Guava und Apache Commons Collections.

Wir haben auch gesehen, wie man mit doppelten Werten umgeht.

Wie immer ist der vollständige Quellcode auf GitHub verfügbar.