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.
| Ansatz | Reihenfolge erhalten? | Am besten wenn |
|---|---|---|
LinkedHashSet | Ja | Ein schneller, abhängigkeitsfreier Einzeiler |
HashSet | Nein | Reihenfolge spielt keine Rolle und Geschwindigkeit ist entscheidend |
stream().distinct() | Ja | Deduplizierung 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
Was man aus der Ausführung mitnehmen kann:
- Die ursprüngliche Liste behält alle 7 Elemente, einschließlich der wiederholten
javaundsql, weil eineListDuplikate 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)gibttrueaus, 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.