W3docs

Duplikate aus einer Liste in Java entfernen

Duplikate aus einer Java-Liste entfernen mit HashSet, LinkedHashSet oder Stream.distinct().

Eine List in Java erlaubt Duplikate per Design. Wenn jeder Wert nur einmal vorkommen soll, müssen Sie die Wiederholungen selbst entfernen. Dieses Kapitel zeigt die idiomatischen Methoden dafür und berücksichtigt, ob die ursprüngliche Einfügereihenfolge erhalten bleibt.

Mit einem LinkedHashSet (Reihenfolge bleibt erhalten)

Der sauberste Ansatz ist, die Liste in ein Set zu kopieren, da ein Set Duplikate automatisch ablehnt. Verwenden Sie LinkedHashSet statt eines einfachen HashSet, damit die Reihenfolge des ersten Auftretens der Elemente beibehalten wird:

List<String> unique = new ArrayList<>(new LinkedHashSet<>(list));

Das Zurückwickeln des Sets in eine ArrayList liefert Ihnen wieder eine List, die für Indizierung oder weitere Verarbeitung bereit ist. Das LinkedHashSet erledigt die gesamte Arbeit: Während es aus der ursprünglichen Liste befüllt wird, verwirft es stillschweigend jedes Element, das es bereits gesehen hat, und seine verkettete Struktur merkt sich die Reihenfolge, in der die Elemente zuerst angekommen sind.

Wenn Sie die Reihenfolge nicht benötigen, ist ein einfaches HashSet geringfügig schneller und verbraucht etwas weniger Speicher. Es durchmischt jedoch die Elementreihenfolge, was selten erwünscht ist, wenn man eine Liste anzeigt. Daher ist LinkedHashSet die sichere Standardwahl.

Mit der Stream API

Ab Java 8 entfernt Stream.distinct() Duplikate in einer einzigen, lesbaren Pipeline. Wie LinkedHashSet behält es die Begegnungsreihenfolge der Elemente bei:

List<String> unique = list.stream()
        .distinct()
        .collect(Collectors.toList());

distinct() vergleicht Elemente mit equals() und hashCode(), genau wie ein Set es tut. Daher müssen Ihre Objekte diese Methoden für benutzerdefinierte Typen korrekt implementieren. Diese Form glänzt, wenn die Deduplizierung ein Schritt in einer größeren Pipeline ist — Sie können filter, map oder sorted darum herum verketten, ohne eine temporäre Sammlung einzuführen.

Vergleich der Ansätze

Beide gängigen Techniken basieren auf equals/hashCode und bewahren beide die Einfügereihenfolge; der Unterschied ist hauptsächlich Stil und Kontext.

AnsatzReihenfolge erhalten?Am besten wenn
LinkedHashSetJaEin schneller, abhängigkeitsfreier Einzeiler
HashSetNeinReihenfolge spielt keine Rolle und Geschwindigkeit ist entscheidend
stream().distinct()JaDeduplizierung ist Teil einer größeren Stream-Pipeline

Ein wichtiger Punkt für alle: Sie erstellen eine neue Sammlung, anstatt die Quelle zu verändern. Wenn Sie die Deduplizierung an Ort und Stelle durchführen müssen, können Sie stattdessen die Liste leeren und die eindeutigen Elemente erneut hinzufügen oder das Ergebnis der gleichen Variable zuweisen.

Praktisches Beispiel

java— editable, runs on the server

Was man aus der Ausführung mitnehmen kann:

  • Die ursprüngliche Liste behält alle 7 Elemente, einschließlich der wiederholten java und sql, weil eine List Duplikate erlaubt.
  • Das LinkedHashSet-Ergebnis hat nur 4 Elemente — [java, sql, api, rest] — und sie erscheinen in der Reihenfolge des ersten Auftretens, nicht sortiert oder durchgemischt.
  • Das stream().distinct()-Ergebnis ist identisch in Größe und Reihenfolge, was bestätigt, dass die beiden Techniken hier austauschbar sind.
  • deduped.equals(viaStream) gibt true aus, da zwei Listen gleich sind, wenn sie dieselben Elemente in derselben Reihenfolge enthalten.
  • Die ursprüngliche tags-Liste bleibt unverändert, sodass die Deduplizierungsoperationen neue Listen erzeugt haben, anstatt die Quelle zu verändern.

Übung

Übung
Welcher Collection-Typ entfernt Duplikate und bewahrt dabei die ursprüngliche Einfügereihenfolge der Elemente?
Welcher Collection-Typ entfernt Duplikate und bewahrt dabei die ursprüngliche Einfügereihenfolge der Elemente?
Was this page helpful?